If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register or Login
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

[RESOLVED] Winsock UDP slows down to a stall.

I am the designated coder for my college's engineering club's robot team and our goal is to pass data from one laptop to another via ad hoc wifi. (We need quick updates, not through-put, and not ACK)

The code below works great on the localhost, but when I take the client app to another PC (Windows 7 32bit w/Visual Studio 2012) communication quickly begins to slow down into a near stall. The client program only responds about every four seconds (or more). The real oddity is after a few minutes two-way communication begins again briefly only to stall once more.

I am hoping someone will take a look and see what I am missing.

Info:

The code is in a form inside a 25ms timer and the data buffers are shown in labels. There is no extra code.
WireShark shows the server sending UDP packets, and the client sending UDP packets about four to eight seconds.
I tired changing the buffers, the timeout, when WSACleanup() is called... my knowledge in this area is limited.

Re: Winsock UDP slows down to a stall.

Re: Winsock UDP slows down to a stall.

Final addition: I swapped the client and the server apps on the two test PCs. With this, everything works as intended and there is no delay in communication. Does anyone have suggestions to where to begin to look for compatibility issues?

Re: Winsock UDP slows down to a stall.

Originally Posted by SugarBombs

[...] There is no extra code. [...]

I strongly doubt that: Your snippets are not even compilable C(++) modules, even less functional Windows applications.

Your indentation suggests that a bunch of your variables is global (probably a bad idea to begin with), but the incompleteness of the snippets doesn't allow a clear distinction. I can't really tell you what might be the concrete problem, even more so since it seems to depend on which Windows version the client runs.

IMO you should tackle the prolem at a really fundamental level: If these actually are meant to be Windows Forms applications (which I only can conclude from the forum section you posted in; there's no other indication), then why don't you use the .NET framework facilities offered for network communication, in particular the stuff from the System::Net::Sockets namespace, more specifically the UdpClient class? It's generally a bad idea to mix managed and native code without a real need to do so (has been discussed aroud here quite frequently).

It should be no problem to reimplement what you posted based on the .NET framework. If, however, for any reason, you really want to preserve most of the code above but still use it in a Windows Forms app, I'd recommend trying to clearly separate the managed and native parts by running the native code in one or more separate threads, merely passing the information to be transceived between the native thread(s) and the Windows Forms GUI thread. However, already the implementation of that multithreading and intra-app communication infrastructure would be more complex than the code you posted, and that wouldn't even implement the tiniest bit of your client/server functionality. So you see: That hybrid approach would considerably complicate things and should only be used if there's a real need.

However, if this isn't meant to be a Windows Forms app at all and you just posted in the wrong forum section, you should repost your query in a more appropriate section like that on network programming (or wait for a moderator to move the thread).

I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

Re: Winsock UDP slows down to a stall.

I was unclear. The statement about no extra code was intended to state there is no extra code outside the posted code and the supporting code for a form. ie, serial port, USB, or other I/Os that could be a conflict in resources.

Yes, this is a windows form application, we desire to have incoming data displayed for the user.

My area of knowledge is in C for MCU firmware and the only C++ experience I have is making this form app. Thank you for the suggestions, I am looking into links provided and looking into what code is managed or native.

Re: Winsock UDP slows down to a stall.

Ok, the sample behind your link sets up a UDP client, but it doesn't use the UdpClientclass. I'd recommend to use the highest abstraction available (UdpClient in this case) unless there really is a good reason to directly deal with the low-level stuff (Socket). I didn't inspect your native code close enough to be completely sure there's no reason for low-level manipulations, but at least that's the general direction.

As to where to place the code, make your UdpClient object a member of your form class. Construct it as soon as you have the information available you need for construction. If that information is already known at compile time, a good place for constructing the UDP client object is the Form::Load event handler. (Constructing it in your form class' constructor is also possible but may be problematic in case construction fails, so I'd recommend against that.)

For handling the actual communication, I'd recommend using the asynchronuous methods (BeginSend(), EndSend(), BeginReceive(), EndReceive()). There are also synchronuous (i.e. blocking) methods for the same tasks which may seem easier to use, but using them in the GUI thread can be quite problematic. In particular doing synchronuous receive will make your app respond much less smoothly, even if you can expect to receive datagrams at a relatively high rate. And should the receive data stream cease it would simply make your app hang... Once you got asynchronuous communication up and running, it will not only let your app run smoother, it will also considerably reduce the risk of screwing up everything with just a small code change.

Admittedly, if you have just done low-level firmware programming in C by now, encountering the .NET framework and C++/CLI may be sort of a culture shock. The Wikipedia article on managed code may at least help to clarify the distinction between that and native code.

Last edited by Eri523; February 16th, 2013 at 06:12 PM.

I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

Re: Winsock UDP slows down to a stall.

Working off the MSDN provided sample code I added the BeginReceive Method to my code. The code has an error I am unsure how to fix. The error is "no user suitable conversion defined from "System::Object ^" to "UdpState" exists" in the following lines:

Re: Winsock UDP slows down to a stall.

Fine! I have a few supplementary coments on your code, though:

For my taste your code contains way too many statics. I'd recomend to turn them into ordinary (i.e. instance) form class members (even though, actually, from the technical POV it doesn't even make that much of a difference when you instantiate the form class only once, which is the common way to use the main form class). In case the reason why they're static is that you only managed to construct the callback delegate for a static callback function: Construction of a delegate referring to an instance member function takes two constructor parameters, the first being the class instance to call the function on. So the correct construction syntax for your receive callback would be gcnew AsyncCallback(this, &Form1::ReceiveCallback). And of course this construction syntax only works from within an instance member function, since in a static one this is unknown. IMO the MS documentation is not quite clear about that.

Console::WriteLine() is not of much use in a Windows Forms app since there is no console. Better replace these with Debug::WriteLine(). Note that Debug::WriteLine() with two string parameters (the format plus one string field) needs special consideration since Debug::WriteLine() has an overload taking two string parameters with a different meaning. Such calls should be translated like this:

Code:

Debug::WriteLine(String::Format("Received: {0}", receiveString));

Did you ever try to use the Forms Designer for your main form since you added the UdpState class declaration to the .h file? I'm asking because a class declaration at that place can be quite problematic, see http://forums.codeguru.com/showthrea...-form-designs!. And while in general encapsulating pieces of information that belong together in a class is a good idea, I don't really see that much of a need for that class here unless you're intending to pass that information packet around to member functions of other classes. Otherwise two ordinary form class instance members would be quite sufficient. Also, you constructed your UdpClient specifying the IPEndPoint, so there's not only not much use in passing the two in a bundle because the UDP client already knows its endpoint anyway, you also would get an exception thrown when you try to specify the endpoint again in a call to one of the send functions.

I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

Re: Winsock UDP slows down to a stall.

Yes, the form designer errors out. I am attempting to move the class declaration elsewhere. After completing the class wizard the code does not compile. I am looking into this.

Yes, there is an exception when trying to send data back out. You mention there is no need to pass the endpoint, however I am unsure how to implement EndReceive() without specifying the required field requesting an endpoint.

Re: Winsock UDP slows down to a stall.

I suspect the MSDN sample is somewhat misleading about the nature of the second parameter to EndReceive(). The parameter is named remoteEP and its type is IPEndPoint^% (as opposed to IPEndPoint^), so it's a tracking reference that allows the function called to modify the variable you pass. So I'd bet it's an output parameter to which the asynchronuous receive operation writes the endpoint info about the remote end sending the received data which it has extracted from the received UDP packet. So far MSDN is just unclear. The really misleading part, however, is that the code sample initializes the variable passed as that parameter with the information taken from the UdpState object which suggests a meaning that the parameter most probably simply doesn't have.

Is it really EndReceive() that throws the exception? Probably not I'd say. And which type of exception is it?

Also, now I know you got the idea of making the functions in question static from the MSDN sample. Unfortunately, just the fact that MSDN does it doesn't automatically make it good style, and I still don't like it. I don't like all these C-style casts either, BTW, and usually avoid them in favor of the clearer C++-style casts (though they demand a bit more of typing).

Last edited by Eri523; February 17th, 2013 at 08:48 PM.

I was thrown out of college for cheating on the metaphysics exam; I looked into the soul of the boy sitting next to me.

This is a snakeskin jacket! And for me it's a symbol of my individuality, and my belief... in personal freedom.

Re: Winsock UDP slows down to a stall.

After a quick read, I have an idea about the differences between C Style casts and C++-style casts, I will convert the C Style casts over to C++. Also, I briefly looked into static functions. Removing static creates an error due to how the ReceiveCallback is called. I will look into this as well.

The exception was caused by the send() call. I do not have the exception text.

The code is now using the output parameter of EndReceive() to gather the IP address of the client. From there the receiving socket is closed and a sending socket with the acquired IP address is open to send a reply. I would imagine there is a way to send data back without opening another socket. Everything is working excellent, so much better than using socket()! (silly me)

Well, I would like to offer beer money for your time in replying to my newbie questions, just PM a PayPal address if you wish. Thank you.