UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

#1 2013-07-05 08:54 PM

nfoster
Member
Registered: 2013-07-05
Posts: 5

Problems with BSD's recv() function

Hello,

I'm developing a simple UDP client/server connection in C++ between my desktop computer (the server) and a microcontroller (client). The microcontroller is able to request data from the server, which acknowledges the request and sends data. I've checked with TCPDump and the connection exists. However, the microcontroller always seems to receive 0 bytes, but doesn't give an error. I was thinking perhaps the socket should be set to non blocking, but I don't think that will make a difference. Any ideas?


Thanks,
Natalie

Offline

#2 2013-07-06 02:41 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Problems with BSD's recv() function

If it were non-blocking, the recv() should return -1 with errno set to EAGAIN/EWOULDBLOCK in the case of nothing currently ready to receive...  A return of zero should always and only indicate that the peer has closed the connection...

Oh, wait a minute...  You said this is UDP?  I was thinking TCP since you mentioned a "connection" being established...  There are no real connections with UDP...  But, I assume you've called connect() on the UDP socket?  That would explain why you're using plain old recv() instead of recvfrom(), as would normally be expected in a UDP-based app...  That's just a simple shortcut for associating a remote peer address with the UDP socket, but doesn't establish any sort of true connection really...

But, anyway, a UDP recv*() can indeed return zero if the peer sends a zero length datagram, which is allowed...  So, I'm guessing that must be what's going on...  But, without seeing any code, I can only guess...

Offline

#3 2013-07-08 04:38 PM

nfoster
Member
Registered: 2013-07-05
Posts: 5

Re: Problems with BSD's recv() function

Thanks for the reply!

I made a mistake and I am actually using the recvfrom() function. I've called connect on the UDP socket, but nothing seems to change if I don't call it. When I call the recvfrom() function, it returns however many bytes are in the receive buffer, which is 0. It does not return an error of -1. How can I test if it is set to blocking? Isn't it blocking by default? Here is the piece of my code I'm having trouble with:

    int rec = recvfrom(s, (char *)&recv_buffer, 4096, 0,
            (struct sockaddr*)&server, &server_length);
       
   
        if(rec == -1) {
            LED0_IO = 1;
           
        }

        else if (rec == 0) {
            LED1_IO = 1;

        }

        //if (rec > 0)
        else  {
            LED2_IO = 1;
            LED0_IO = 0;
            closesocket(s);
            return 0;
        }


I get output not on a console, but from LEDs on my microcontroller. The receive buffer is initialized to "" or empty.

Last edited by nfoster (2013-07-08 04:38 PM)

Offline

#4 2013-07-08 08:24 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Problems with BSD's recv() function

int rec = recvfrom(s, (char *)&recv_buffer, 4096, 0,
            (struct sockaddr*)&server, &server_length);

Offline

#5 2013-07-09 02:23 PM

nfoster
Member
Registered: 2013-07-05
Posts: 5

Re: Problems with BSD's recv() function

Regarding the zero-length datagram: The datagram being sent by the server is 22 bytes long. I have verified this with WinDump. The strange part is that I can initialize the recv_buffer to something other than empty, like "12345", and when I call recvfrom(), it returns the length of the buffer. I will include a more detailed portion of my code below.

Regarding the setting of server_length: Yes, it has been predefined as

server_length = sizeof(struct sockaddr_in);

Regarding the misaddressing of LEDs: I have checked that they are consistent with what I see on the board.

Regarding the testing of client code elsewhere: This is the bizarre part. This code that I am using is nearly identical to the client code that I have run on the same computer as a server, and also across the network. The problem probably comes from Microchip being picky and making things difficult to debug. Anyway, here is a more inclusive snippet of code. I've modified it a bit:


   

unsigned short port_number = 12345;
	int server_length;
	char send_buffer[4096] = "hi";	
	char recv_buffer[4096] = "";
	struct sockaddr_in server;		
	struct sockaddr_in client;
	char b1 = 146;
	char b2 = 5;
	char b3 = 8;
	char b4 = 30;
	char b5 = 20;

	BerkeleySocketInit();

	SOCKET s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

	//int fn = ioctl(s, (int)FIONBIO, 1);

	//clearing out the server struct
	memset((void *)&server, '\0', sizeof(struct sockaddr_in));

	//setting server parameters
	server.sin_family = AF_INET;
	server.sin_port = port_number;

	//setting server address
	server.sin_addr.S_un.S_un_b.s_b1 = b1;
	server.sin_addr.S_un.S_un_b.s_b2 = b2;			
	server.sin_addr.S_un.S_un_b.s_b3 = b3;
	server.sin_addr.S_un.S_un_b.s_b4 = b5;

	//clearing out client struct
	memset((void*)&client, '\0', sizeof(struct sockaddr_in));

	//setting client parameters
	client.sin_family = AF_INET;
	client.sin_port = port_number;
	
	//setting client address
	client.sin_addr.S_un.S_un_b.s_b1 = b1;
	client.sin_addr.S_un.S_un_b.s_b2 = b2;			
	client.sin_addr.S_un.S_un_b.s_b3 = b3;
	client.sin_addr.S_un.S_un_b.s_b4 = b4;
	
	//don't know if these are necessary
	int bin = bind(s, (struct sockaddr*)&client, sizeof(struct sockaddr_in));
	int con = connect(s, (struct sockaddr*)&server, sizeof(struct sockaddr_in));


	server_length = sizeof(struct sockaddr_in);
	int bufsize = (int)strlen(recv_buffer);
	

	//initialize sen to -1 (error code)
	int sen = -1;	

	while(1) {

 		
	
        StackTask();

        // This tasks invokes each of the core stack application tasks
        StackApplications();
	

	
		//update to what the outcome of sendto() is
		if(sen == -1) {
			sen = sendto(s, send_buffer, (int)strlen(send_buffer) + 1, 0,
				(struct sockaddr *)&server, server_length);
		}

		//when it works, start receiving
		else if(sen > 0) {

			int rec = recvfrom(s, (char *)&recv_buffer, bufsize, 0,
				(struct sockaddr*)&server, &server_length);
			
		
			if(rec == 0) {
				LED0_IO = 1;
				LED1_IO = 0;
				LED2_IO = 0;
				
	 		}
	
			else if (rec == 25) {
				LED0_IO = 0;
				LED1_IO = 1;
				LED2_IO = 0;
	
			}
	
			else  {
				LED2_IO = 1;
				LED1_IO = 0;
				LED0_IO = 0;
				closesocket(s);
				return 0;
			}
	
			//closesocket(s);
		}
		
	}

Offline

#6 2013-07-09 07:49 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,839
Website

Re: Problems with BSD's recv() function

int bufsize = (int)strlen(recv_buffer);

Offline

#7 2013-07-09 08:23 PM

nfoster
Member
Registered: 2013-07-05
Posts: 5

Re: Problems with BSD's recv() function

The bufsize definitely seemed to be the problem. Everything works the way I want it to now!

The port number was a huge issue in the past, in which I used the htons() function, but it didn't work well with the Microchip API. port_number on its own did the trick.

I know the IP address is coded in a very strange way, but under very specific circumstances it wouldn't work otherwise... but now I am able to send data from the server to my microcontroller and it works like a charm! Thank you so much for your help, it is greatly appreciated.

Offline

#8 2013-07-11 12:37 AM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,239

Re: Problems with BSD's recv() function

Is this an 8, 16 or 32 bit Microchip chip?

If you're using Microchip's toolchain then it's not "real" C and weird things are to be expected.

Offline

#9 2013-07-13 05:24 PM

nfoster
Member
Registered: 2013-07-05
Posts: 5

Re: Problems with BSD's recv() function

It's a 32 bit microchip. Yeah I realized that not all of the C functions and attributes were spot-on with this thing and it was really annoying. But I figured it all out it seems (whew!)

Offline

#10 2013-07-14 08:17 AM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,239

Re: Problems with BSD's recv() function

I only have experience with 8 bit ones, IIRC there an int was 16 bits. 32 bit versions probably aren't too bad.

Offline

Board footer

Powered by FluxBB