C Board  

Go Back   C Board > General Programming Boards > Networking/Device Communication

Reply
 
LinkBack Thread Tools Display Modes
Old 11-12-2007, 12:03 PM   #1
Registered User
 
Join Date: Nov 2007
Posts: 3
recv() malfunctioning in a pthread?

Hello -

I've got a simple client and simple server setup going. Right now, my client uses send() twice: first to send a header, and then to send a request. I know that this functionality is working correctly (I'll explain later).

On the server side, I started simple; just had a while(1) loop accepting new connections and then recv()'ing the two send()'s. This worked just fine, and I could pull all the data that was sent and print it out to ensure it was correct.

However, to allow for multiple requests to be processed at once, I wanted to detach a new pthread for every connection I had incoming. So I did something like this:

Code:
void *processRequest (void* arg) {
   int socket = (int) arg;
   char buf1[100];
   recv(socket, buf1, 100, 0);
   char buf2[100];
   recv(socket, buf2, 100, 0);   // BLOCKS HERE
   close(socket);
   // Do stuff with the buffers here.
}

int main() {
   // Set up socket stuff here
   pthread_attr_t attr;
   pthread_attr_init(&attr);
   pthread_attr_setstacksize(&attr, 1024*1024);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   while(1) {
      int connection = accept(socket, null, null);
      pthread_t thread;
      pthread_create (&thread, &attr, processRequest, (void *) connection);
   }
}
As noted in the comment in the code above, the program gets stuck in the second recv() call when I use pthreads. I've got no idea why. Does anyone have any suggestions?

Thanks.
th3void is offline   Reply With Quote
Old 11-12-2007, 12:13 PM   #2
Registered User
 
Codeplug's Avatar
 
Join Date: Mar 2003
Posts: 3,902
How big is the header and how big is the payload? You are prob. reading both wth the first recv.

gg
Codeplug is online now   Reply With Quote
Old 11-12-2007, 12:16 PM   #3
Senior software engineer
 
brewbuck's Avatar
 
Join Date: Mar 2007
Location: Portland, OR
Posts: 5,768
I don't see anything wrong that would cause this to stop working just because you started using threads. A few things though:

Don't cast the "connection" descriptor to void * to pass it to the thread function. Casting between integer and pointer types works on some platforms but not everywhere. Going from int to void * to int again could lose information. Instead you should be passing an address of some kind. Allocate a little buffer to store the connection number and pass a pointer to that instead. Do NOT just pass a pointer to the connection variable itself. It might get overwritten by an immediately following connection before the first thread gets a chance to extract its value. In other words, that's a race condition.

You also don't check the return value of recv(). The call to recv() is not guaranteed to actually return 100 bytes -- it could return less. It may require multiple calls to read all the data. Alternately you could pass MSG_WAITALL to try to read all the bytes in one call, but it still might error. You have to check.

And why do these very simple threads need a 1 megabyte stack?
brewbuck is offline   Reply With Quote
Old 11-12-2007, 12:30 PM   #4
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,693
> my client uses send() twice: first to send a header, and then to send a request.
But there's no reason for the receiver to see that division.

It's like reading a file, you have no idea how the file was written (a byte at a time, a line at a time). All you see is a stream of bytes, and that's it.

For recv(), it might take one call to get all the data, it might take 3 or 4. Even if it takes 2 calls, there's no reason to assume that it matches the packet sizes you sent.

ALL the responsibility for parsing the stream rests with you. The network just transports it in packets which are convenient to transport, and reassembles the stream in the order it was sent.

You should also be aware that send() doesn't guarantee to send the whole message in one call, so you need to pay close attention to that return result as well.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Old 11-12-2007, 12:39 PM   #5
Registered User
 
Join Date: Nov 2007
Posts: 3
Thanks for the response, guys.

t brewbuck: You are correct that I will need to eventually allocate for that int, I am still in the testing phase and I was sure that at least the part that passed the connection number was working fine.

To all three of you, well, you were right in that I should be checking the value of recv(). However, I'm still a bit confused. The header is variable length unfortunately. It's a username and then an int to describe the size of the payload. More on this later.

What is bothering me is the following: if I execute the two recv() calls directly from the while() loop, rather than creating a thread, the first recv() returns 9 bytes and the second recv() returns 50. If I do this in the pthread instead, the first returns 59 bytes (and as Codeplug mentioned, this is both send()'s which is why it is blocking).

I guess I was incorrect in thinking that each recv() would only process the output from one send(); whoops. However, since this is the case, do either of you have any parsing suggestions? Since we can see from running directly in the while() loop it appears there is no guarantee both packets have been sent by the time I call the first recv(), I'm not sure how to decide whether or not I need a second recv(). And because the header isn't fixed length I don't know how to tell recv() ONLY to pull the data from the header with the first call.

Yick...
th3void is offline   Reply With Quote
Old 11-12-2007, 12:44 PM   #6
Registered User
 
Codeplug's Avatar
 
Join Date: Mar 2003
Posts: 3,902
The client typically needs to know how much data it can expect to recieve. Since the header is variable length, then the first member of the header could be "size of header".

Then you just need functions for "send till it's sent" and "read till it's read"

gg
Codeplug is online now   Reply With Quote
Old 11-12-2007, 12:45 PM   #7
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,693
You need something in the data stream to tell you where the boundaries are.

For example, HTML separates the header from the body with a blank line. In the first instance, you just accumulate data until that is seen (and save whatever comes after it for later), then parse the header.

Another way is to prefix each message with a length, so you can read say 1 or 2 bytes initially, then know how many more to expect for the next 'frame' of data.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Old 11-12-2007, 01:00 PM   #8
Registered User
 
Join Date: Nov 2007
Posts: 3
Ah, well admittedly this is a tiny, tiny bit of a school project that I'm working on. This recv() message problem had stumped me for more than 8 hours now (dumb, I know) so I'm glad you were able to assist on that. As far as the message headers, I can't really alter their structure as it's specified in the assignment, so that'll be a big pain in the rear. I'll slave away for a few more days and see if I can't get anything cranked out. Thanks for all of your help.
th3void is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Question about recv carrotcake1029 Networking/Device Communication 2 02-26-2009 02:10 PM
Pthread recv Blocks scioner C Programming 6 03-13-2008 08:45 PM
The Pthread Hell matott Linux Programming 1 04-10-2005 05:59 AM
recv() afisher Networking/Device Communication 3 03-24-2004 05:32 PM
non blocking recv rohit Linux Programming 4 03-05-2002 09:35 PM


All times are GMT -6. The time now is 07:40 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22