CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 18
  1. #1
    Join Date
    Feb 2013
    Posts
    11

    [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.

    The Server:

    Code:
    #define DEFAULT_PORT 12400
    
    timeval send_timeout = {0, 0};
    timeval recv_timeout = {0, 20000};
    
    char *ip_address= NULL;
    unsigned short port=DEFAULT_PORT;
    int retval;
    int fromlen;
    struct sockaddr_in local, from;
    WSADATA wsaData;
    SOCKET listen_socket, conn_socket;
    signed char select_return;
    
    
    unsigned char socket_in_data[64] = {};
    unsigned char socket_out_data[64] = {};
    unsigned char usb_in_data[64];
    char recv_buf[64] = {}; 
    char send_buf[64] = {};
    
    
    unsigned char socket_status;
    unsigned char socket_send_status;
    unsigned char socket_receive_status;
    
    char retval_recv = 0;
    char retval_send = 0;
    
    				 socket_status = 0;
    				 socket_send_status = 0;
    				 socket_receive_status = 0;
    
    				 while(1)
    				 {
    					 // Request Winsock version 2.2
    					 if ((retval = WSAStartup(0x202, &wsaData)) != 0)
    					 {
    						 // error - WSAStartup()
    						 break;
    					 }
    
    					 local.sin_family = AF_INET;
    					 local.sin_addr.s_addr = (!ip_address) ? INADDR_ANY:inet_addr(ip_address);
    
    					 // Port MUST be in Network Byte Order
    					 local.sin_port = htons(port);
    					 listen_socket = socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP);
    
    					 if (listen_socket == INVALID_SOCKET){
    						 // eeror - socket() failed
    						 break;
    					 }
    
    					 if (bind(listen_socket, (struct sockaddr*)&local, sizeof(local)) == SOCKET_ERROR)
    					 {
    						 //error - bind() failed with error
    						 break;
    					 }
    
    					 fromlen =sizeof(from);        
    					 conn_socket = listen_socket;
    
    
    					 
    					 int send_buf_size_int = 64;
    					 const char* send_buf_size = (const char*)&send_buf_size_int;
    					 setsockopt(conn_socket, SOL_SOCKET, SO_SNDBUF, send_buf_size, NULL);
    
    					 fd_set read_mask;
    					 FD_ZERO(&read_mask);
    					 FD_SET(conn_socket, &read_mask);
    
    					 select_return = select(conn_socket + 1, &read_mask, (fd_set *)0, (fd_set *)0, &recv_timeout);
    
    					 if(select_return < 0)
    					 {
    						 // error - select functions returned -1 error value	
    						 socket_receive_status = 31;						
    
    					 }
    					 else if(select_return == 0)
    					 {
    						 // error - select functions returned 0 timeout value	
    						 socket_receive_status = 32;
    
    						 // break the select() loop when there is no more data to read
    						 socket_create_flag = true;						 
    
    					 }
    					 else
    					 {						 															
    
    						 retval_recv = recvfrom(conn_socket,recv_buf, 64, 0, (struct sockaddr *)&from, &fromlen);   
    
    						 if (retval_recv == SOCKET_ERROR)
    						 {
    							 //error - recv() failed
    							 socket_receive_status = 33;
    
    						 } else {
    
    							 // recv successful, update data buffers
    							 socket_receive_status = 37;
    							 memcpy(&socket_in_data, &recv_buf, sizeof(recv_buf));
    							 memcpy(&socket_out_data, &recv_buf, sizeof(recv_buf)); //temp
    
    						 }
    
    					 } //end select
    
    					 ///////
    
    					 fd_set write_mask;
    					 FD_ZERO(&write_mask);
    					 FD_SET(conn_socket, &write_mask);
    
    					 select_return = select(conn_socket + 1, (fd_set *)0, &write_mask, (fd_set *)0, &send_timeout);
    
    					 if(select_return < 0)
    					 {					 
    						 // error - select function returned -1 error value	
    						 socket_send_status = 20;
    					 }
    					 else if(select_return == 0)
    					 {
    						 // error - select function returned 0 timeout value
    						 socket_send_status = 21;
    					 }
    					 else 
    					 {
    
    						 // send data
    						 socket_send_status = 27;
    						 const char* send_buf = (const char*)&socket_out_data;		
    						 retval_send = sendto(conn_socket, send_buf, 64, 0, (struct sockaddr *)&from, fromlen);
    
    						 if (retval_send == SOCKET_ERROR)
    						 {
    							 //error send() failed
    							 socket_send_status = 22;
    						 }
    
    					 } //end select
    
    					 socket_status = 1;					
    					 break;
    				 } // end while
    
    				 // Update UI for status and errors
    				 this->label_socket_status_codes->Text = socket_status + " - " + socket_send_status + " - " + socket_receive_status + " - " + WSAGetLastError();
    
    				 closesocket(conn_socket); 
    				 WSACleanup();


    The Client:

    Code:
    nsigned char display_counter;
    
    #define DEFAULT_PORT 12400
    
    timeval send_timeout = {0, 0};
    timeval recv_timeout = {0, 20000};
    
    char *ip_address= NULL;
    unsigned short port=DEFAULT_PORT;
    int retval;
    int fromlen;
    struct sockaddr_in local, from;
    WSADATA wsaData;
    //SOCKET listen_socket, msgsock;
    signed char select_return;
    
    
    //client
    char *server_name= "192.168.0.100";
    struct sockaddr_in server;
    struct hostent *hp;
    SOCKET  conn_socket;
    unsigned int addr;
    //client
    
    
    unsigned char socket_in_data[64] = {};
    unsigned char socket_out_data[64] = {};
    unsigned char usb_in_data[64];
    char recv_buf[64] = {}; 
    char send_buf[64] = {};
    
    unsigned char socket_status;
    unsigned char socket_send_status;
    unsigned char socket_receive_status;
    
    display_counter++;
    				 socket_out_data[0] = display_counter;
    
    
    				 while(1) {
    
    					 if ((retval = WSAStartup(0x202, &wsaData)) != 0)
    					 {
    						 //error - failed to startup
    						 socket_status = 2;
    						 break;
    					 }					 		
    					 // Attempt to detect if we should call gethostbyname() or gethostbyaddr()
    					 if (isalpha(server_name[0]))
    					 {   // server address is a name
    						 hp = gethostbyname(server_name);
    					 }
    					 else
    					 { // Convert nnn.nnn address to a usable one
    						 addr = inet_addr(server_name);
    						 hp = gethostbyaddr((char *)&addr, 4, AF_INET);
    					 }
    					 if (hp == NULL )
    					 {
    						 //error - cannot resolve address 
    						 socket_status = 3;
    					 }
    
    					 // Copy the resolved information into the sockaddr_in structure
    					 memset(&server, 0, sizeof(server));
    					 memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
    					 server.sin_family = hp->h_addrtype;
    					 server.sin_port = htons(port);
    
    					 // Open a socket
    					 conn_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 
    
    					 if (conn_socket <0 )
    					 {
    						 // error - opening socket
    						 socket_status = 4;
    					 }  
    					 if (connect(conn_socket, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
    					 {
    						 // error - connect failed
    						 socket_status = 5;
    					 }
    					 	
    
    
    					 int send_buf_size_int = 64;
    					 const char* send_buf_size = (const char*)&send_buf_size_int;
    					 //setsockopt(s, SOL_SOCKET, SO_RCVBUF, tete, NULL);
    					 setsockopt(conn_socket, SOL_SOCKET, SO_SNDBUF, send_buf_size, NULL);
    					 
    
    
    					 fd_set write_mask;
    					 FD_ZERO(&write_mask);
    					 FD_SET(conn_socket, &write_mask);
    
    					 select_return = select(conn_socket + 1, (fd_set *)0, &write_mask, (fd_set *)0, &send_timeout);
    
    					 if(select_return < 0)
    					 {					 
    						 // error - select function returned -1 error value	
    						 socket_send_status = 20;
    					 }
    					 else if(select_return == 0)
    					 {
    						 // error - select function returned 0 timeout value
    						 socket_send_status = 21;
    					 }
    					 else 
    					 {
    						 socket_send_status = 27;
    						 const char* send_buf = (const char*)&socket_out_data;		
    						 select_return = send(conn_socket, send_buf, 64, 0);
    
    						 if (select_return == SOCKET_ERROR)
    						 {
    							 //error send() failed
    							 socket_send_status = 22;
    						 }
    
    					 } //end select
    
    					 //////////
    
    					 fd_set read_mask;
    					 FD_ZERO(&read_mask);
    					 FD_SET(conn_socket, &read_mask);
    					 
    					 select_return = select(conn_socket + 1, &read_mask, (fd_set *)0, (fd_set *)0, &recv_timeout);
    
    					 if(select_return < 0)
    					 {
    						 // error - select functions returned -1 error value	
    						 socket_receive_status = 31;
    						 break;
    
    					 }
    					 else if(select_return == 0)
    					 {
    						 // error - select functions returned 0 timeout value	
    						 socket_receive_status = 32;
    					 }
    					 else
    					 {						 															
    						 retval = recv(conn_socket, recv_buf, 64, 0);   
    
    						 if (retval == SOCKET_ERROR)
    						 {
    							 //error - recv() failed
    							 socket_receive_status = 33;
    
    						 } else {
    
    							 // recv successful, update data buffers
    							 socket_receive_status = 37;
    							 memcpy(&socket_in_data, &recv_buf, sizeof(recv_buf));
    						 }
    					 } //end select
    
    					 socket_status = 1;
    					 break;
    
    				 } //end while
    
    
    				 // Update UI for status and errors
    				 this->label_socket_status_codes->Text = socket_status + " - " + socket_send_status + " - " + socket_receive_status + " - " + WSAGetLastError();
    
    				 closesocket(conn_socket);
    				 WSACleanup();


    Thank you.

  2. #2
    Join Date
    Feb 2013
    Posts
    11

    Re: Winsock UDP slows down to a stall.

    Also, the firewalls are disabled.

  3. #3
    Join Date
    Feb 2013
    Posts
    11

    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?

  4. #4
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: Winsock UDP slows down to a stall.

    Quote Originally Posted by SugarBombs View Post
    [...] 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.

  5. #5
    Join Date
    Feb 2013
    Posts
    11

    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.

  6. #6
    Join Date
    Feb 2013
    Posts
    11

    Re: Winsock UDP slows down to a stall.

    I am looking at a few examples (link) of UPDClient Class, and I am unsure where to place this code into the form. Any pointers would help out greatly. Thank you.

  7. #7
    Join Date
    Feb 2013
    Posts
    11

    Re: Winsock UDP slows down to a stall.

    So far using the UdpClient method I am able to send data from a client PC to the server PC just fine. (The code is simple compared to my original method.)

    However, I am trying to make remove the blocking. I tired the following which does not compile.

    Code:
    receivingUdpClient->SetSocketOption ( SocketOptionLevel::Socket, SocketOptionName::SendTimeout, 100 );
    Any pointers are welcome.

  8. #8
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    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 UdpClient class. 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.

  9. #9
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Re: Winsock UDP slows down to a stall.

    Quote Originally Posted by SugarBombs View Post
    [...] I tired the following which does not compile.

    Code:
    receivingUdpClient->SetSocketOption ( SocketOptionLevel::Socket, SocketOptionName::SendTimeout, 100 );
    Of course it doesn't: UdpClient doesn't have such a method.

    As to the blocking, see post #8.
    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.

  10. #10
    Join Date
    Feb 2013
    Posts
    11

    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:

    Code:
    UdpClient^ udpClient = ((UdpState)(asyncResult->AsyncState)).udpClient;
    IPEndPoint^ ipEndPoint =((UdpState)(asyncResult->AsyncState)).ipEndPoint;
    The following code is the main section: (I am unsure if I have created the class properly)

    Code:
    public ref class UdpState
    {
    public : UdpClient^ udpClient;
    public : IPEndPoint^ ipEndPoint;
    };
    
    
    namespace client {
    
    	using namespace System;
    	using namespace System::ComponentModel;
    	using namespace System::Collections;
    	using namespace System::Windows::Forms;
    	using namespace System::Data;
    	using namespace System::Drawing;
    	
    	using namespace System::Net;
    	using namespace System::Net::Sockets;
    	using namespace System::Text;
    		
    	/// <summary>
    	/// Summary for Form1
    	/// </summary>
    	
    	public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
    		Form1(void)
    		{
    			InitializeComponent();		
    		}
    				
    	static bool isMessageReceived;
    
        static void ReceiveCallback(IAsyncResult^ asyncResult)
        {
            UdpClient^ udpClient = ((UdpState)(asyncResult->AsyncState)).udpClient;
            IPEndPoint^ ipEndPoint =((UdpState)(asyncResult->AsyncState)).ipEndPoint;
    
            array<Byte>^ receiveBytes = udpClient->EndReceive(asyncResult, ipEndPoint);
            String^ receiveString = Encoding::ASCII->GetString(receiveBytes);
    
            Console::WriteLine("Received: {0}", receiveString);
            isMessageReceived = true;
        }
    
        static void ReceiveMessages()
        {
            // Receive a message and write it to the console.
            IPEndPoint^ ipEndPoint = gcnew IPEndPoint(IPAddress::Any, 11000);
            UdpClient^ udpClient = gcnew UdpClient(ipEndPoint);
            UdpState^ udpState = gcnew UdpState();
            udpState->ipEndPoint = ipEndPoint;
            udpState->udpClient = udpClient;
    
            Console::WriteLine("listening for messages");
            udpClient->BeginReceive(gcnew AsyncCallback(ReceiveCallback),
                udpState);
    
            // Do some work while we wait for a message. For this example, 
            // we'll just sleep 
            while (!isMessageReceived)
            {
                //Thread::Sleep(100);
            }
    
    ..... more form code ..... then a timer call with
    
    ReceiveMessages();
    
        }
    Thank you for helping out. My community college is rather small I am unable to locate anyone local with proficient C++ knowledge.

  11. #11
    Join Date
    Feb 2013
    Posts
    11

    Re: Winsock UDP slows down to a stall.

    Well, I figured the code issue out and now the code sends data from the server to the client. The receiving code does not block the form when there is no data incoming.

    Next I will attempt to combine send and receive so the client and server can communicate in bidirection. Once I get this working and other bugs worked out I will post the updated code.

  12. #12
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    Thumbs up 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.

  13. #13
    Join Date
    Feb 2013
    Posts
    11

    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.

    Code:
    
    
    
    // code in timer //
    	                     try
    				 {
    
    					 if (isMessageReceived == true) {
    
    						 this->label_socket_status_codes->Text = "true";  
    						 isMessageReceived = false;
    
    						 // Receive a message and write it to the console.
    						 IPEndPoint^ ipEndPoint = gcnew IPEndPoint(IPAddress::Any, 11000);
    						 UdpClient^ udpClient = gcnew UdpClient(ipEndPoint);
    						 UdpState^ udpState = gcnew UdpState();
    						 udpState->ipEndPoint = ipEndPoint;
    						 udpState->udpClient = udpClient;
    
    						 udpClient->BeginReceive(gcnew AsyncCallback(Form1::ReceiveCallback), udpState);
    					 }
    
    				 }
    				 catch ( Exception^ e ) 
    				 {
    					 this->label1->Text = e->ToString();
    				 }
    
    // end code in timer //
    
    
                static void ReceiveCallback(IAsyncResult^ asyncResult)
    		{
    			UdpClient^ udpClient = ((UdpState^)(asyncResult->AsyncState))->udpClient;
    			IPEndPoint^ ipEndPoint = ((UdpState^)(asyncResult->AsyncState))->ipEndPoint;
    
    			
    // unsure how to EndReceive without having the endpoint information passed through
                            array<Byte>^ receiveBytes = udpClient->EndReceive(asyncResult, ipEndPoint);
    			
    			// Copy received data into our application buffer
    			for (char forvar_rcb = 0; forvar_rcb < 1; forvar_rcb++) { // temp: only the first character
    				socket_in_data[forvar_rcb] = receiveBytes[forvar_rcb];
    			}
    				
    // exception when calling Send()
    			udpClient->Send( receiveBytes, receiveBytes->Length );		
    			
    			// close the receiving socket
    			udpClient->Close();
    						
    			// trigger flag to reopen receiving socket
    			isMessageReceived = true;
    			
    		}
    Also, I am attempting to implement the code suggests.

  14. #14
    Join Date
    Jun 2010
    Location
    Germany
    Posts
    2,675

    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.

  15. #15
    Join Date
    Feb 2013
    Posts
    11

    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.

    Here's the code that works for me for other newbies.

    Code:
     
    // code inside a form timer//
                                try
    				 {
    					 if (isMessageReceived == true) {
    
    						 isMessageReceived = false;
    
    						 // create a UDP connection
    						 UdpClient^ udpClient = gcnew UdpClient(11000);
    
    						 // save the connection information to be passed along to call back handler	
    						 UdpState^ udpState = gcnew UdpState();						
    						 udpState->udpClient = udpClient;
    
    						 // begin waiting for incoming data, the function does not block
    						 udpClient->BeginReceive(gcnew AsyncCallback(Form1::ReceiveCallback), udpState);
    					 }
    
    				 }
    				 catch ( Exception^ e ) 
    				 {
    					 this->label1->Text = e->ToString();
    				 }
    
    // end of form timer//
    
    
    // call back handler //
    
              static void ReceiveCallback(IAsyncResult^ asyncResult)
    		{
    			UdpClient^ udpClient = ((UdpState^)(asyncResult->AsyncState))->udpClient;
    
    			IPEndPoint^ ipEndPoint_of_client;
    
    			array<Byte>^ receiveBytes = udpClient->EndReceive(asyncResult, ipEndPoint_of_client);
    
    			// Copy received data into our application buffer
    			for (char forvar_rcb = 0; forvar_rcb < receiveBytes->Length; forvar_rcb++) {
    				socket_in_data[forvar_rcb] = receiveBytes[forvar_rcb];
    			}
    
    			// close the receiving socket			
    			udpClient->Close();		
    
    
    			// aquire IP address of the client sending data
    			IPAddress^ sendback_ipaddress = ipEndPoint_of_client->Address; 
    
    			// convert the IP address into a string for input into UdpClient
    			String^ sendback_ipaddress_string = sendback_ipaddress->ToString();
    
    			// create new socket
    			UdpClient^ sending_UdpClient = gcnew UdpClient(sendback_ipaddress_string, 11000);			 
    			// loopback data received (temp, for testing)			
    			sending_UdpClient->Send( receiveBytes, receiveBytes->Length );
    
    			// close the sending socket
    			sending_UdpClient->Close();
    
    			// trigger flag to reopen receiving socket
    			isMessageReceived = true;
    
    		}

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured