944,026 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Unsolved
  • Views: 13918
  • C++ RSS
You are currently viewing page 1 of this multi-page discussion thread
Apr 28th, 2006
0

Winsock C++ help: receiving data

Expand Post »
Hello, I'm having a problem receiving information with Winsock. I have 2 programs written, one is a server capable of accepting sockets from multiple users, and the other is a simple one socket client.

The server uses an array of a user defined data type with a boolean variable and a socket variable in it, to handle all the clients. It updates at run-time for each user connecting.

After a successful connection is made, both the client and server are put into non-blocking mode using ioctlsocket().

Client send code:
C++ Syntax (Toggle Plain Text)
  1. string strSend = "all this packet information!!";
  2. int sz = strSend.size();
  3. send(m_socket, strSend.c_str(), sz, 0);

Server receive code:
C++ Syntax (Toggle Plain Text)
  1. // check incoming packets
  2.  
  3. for (int c=0; c<nSize; c++) {
  4.  
  5. char recvbuff[1024];
  6. int bytesRecv = 0;
  7.  
  8. // each socket
  9. bytesRecv = recv(nClients[c].m_socket, recvbuff, 1024, 0);
  10.  
  11. if (bytesRecv>0) {
  12. string strRecv = recvbuff;
  13. string output = strRecv.substr(0, bytesRecv);
  14.  
  15. cout << output << endl;
  16.  
  17. }
  18.  
  19. }
  20.  
  21. return;
  22. }

My receiving packet is set at 1024 bytes, but whenever I receive a packet over 10 characters long, my packets tend to stack up. As you see, I cout << output << endl; so that each incoming packet is on its own line. My result is this:

1234567890
1234567890
1234567890
12345678901234567890
12345678901234567890
1234567890
1234567890
12345678901234567890
1234567890
1234567890
1234567890
12345678901234567890

If my packet is say, around 6 characters, I don't ever see this kind of stacking. The larger the packet, the more often they stack. In this case, I use "all this packet information!!", the result is:

all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!all this packet information!!

A stream until it hits 1024 bytes, then it repeats. Help!
Similar Threads
Reputation Points: 10
Solved Threads: 0
Newbie Poster
Mr Violent is offline Offline
22 posts
since Mar 2005
Apr 28th, 2006
0

Re: Winsock C++ help: receiving data

You need a delay on your reading loop.
Need to check for the socket ready befor attempting to read further.

Check out the function readfromstream here: http://www.live555.com/liveMedia/dox...pp-source.html
Reputation Points: 10
Solved Threads: 0
Newbie Poster
luccig is offline Offline
5 posts
since Apr 2006
Apr 28th, 2006
0

Re: Winsock C++ help: receiving data

So you think giving my program a 1 ms delay will correct this issue indefinitely? Hmm, thanks for the feedback. Is there some function that actually checks the socket if it is ready to receive new incoming data? I read about some select() function at some point, but didn't really get into it.

If I follow the example you gave me, I should wait on a 1 ms timer (I have a GetTickCount() timer built into my program already to run a check disconnects routine every minute or so) and run my main loop (with the exception to this check incoming function) in the meantime?

Thanks for the quick and timely reply, helps a lot to know I'm not alone out here.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
Mr Violent is offline Offline
22 posts
since Mar 2005
Apr 30th, 2006
0

Re: Winsock C++ help: receiving data

Hey,

No problem. I had this problem once, and setting a delay actually helped.
My server used to spawn a thread for every incoming request and send data based on some authentification using send(..)
When receiving, first bytes are the actual size of the data to receive, so I know for how long should I be listening. Then in my receiving loop, I had to set some delay until I got everything.

One more thing, in your cout you need to do a flush, to make sure you display the string right away.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
luccig is offline Offline
5 posts
since Apr 2006
Apr 30th, 2006
0

Re: Winsock C++ help: receiving data

Alright. I find it kind-of unreliable to base my receiving loop on a 1ms timer, I figured the winsock method would have something more..solid. I'll try it, thanks!

Also, do you know anything about using select() for this kind of thing?
Reputation Points: 10
Solved Threads: 0
Newbie Poster
Mr Violent is offline Offline
22 posts
since Mar 2005
May 1st, 2006
1

Re: Winsock C++ help: receiving data

Read beej very carefully
http://beej.us/guide/bgnet/output/htmlsingle/bgnet.html
It has an example of how to use select.

Some points to note
> send(m_socket, strSend.c_str(), sz, 0);
Both send() and recv() can fragment the message. There is no guarantee that if you ask to send 20 bytes that it will happen in a single call. Even if the send() is a single call, the recv() can still be fragmented.
Making the whole thing non-blocking just makes this much more likely.

> So you think giving my program a 1 ms delay will correct this issue indefinitely?
Not at all.
Some points to ponder.
1. The sleep duration is a MINIMUM value only, so sleeping for 1 second and returning an hour later would be in spec.
http://msdn.microsoft.com/library/de...base/sleep.asp
"Suspends the execution of the current thread for at least the specified interval."

2. The OS time base is usually 10 or 20mS. Very short sleep periods get rounded up to the base OS scheduling interval.
http://www.geisswerks.com/ryan/FAQS/timing.html
Next OS upgrade, you could be looking for a different answer.

3. The actual amount you sleep will vary according to system load at the time. I mean, if your timer becomes very finely balanced, then all sorts of wierdness could result like
- my program runs fine during the day and crashes in the evening (sensitive to network load)
- my program is OK in debug, but crashes in release mode(*) (sensitive to code performance)
- my program works if I'm playing minesweeper (sensitive to system load)


(*) The much more likely scenario of course is a bug in the code.
Team Colleague
Reputation Points: 5862
Solved Threads: 950
Posting Sage
Salem is offline Offline
7,164 posts
since Dec 2005
May 2nd, 2006
0

Re: Winsock C++ help: receiving data

I've tried using a manual timer delay with GetTickCount(), and I've also tried using select(). When I make a loop and only check incoming data after 1ms (using GetTickCount()) I just get a big chunk of clumped up data every 1ms or whatever timer I set. select() isn't having any effect. Perhaps the information is getting clumped up when I send it? I suppose i'll test around with that now.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
Mr Violent is offline Offline
22 posts
since Mar 2005
May 4th, 2006
0

Re: Winsock C++ help: receiving data

No luck.

Sending loop:
C++ Syntax (Toggle Plain Text)
  1. FD_SET setWrite;
  2. FD_ZERO(&setWrite);
  3. FD_SET(m_socket, &setWrite);
  4. int n = m_socket + 1;
  5. if (select(n, 0, &setWrite, 0, 0) != SOCKET_ERROR) {
  6. string strSend = "all this packet information!!";
  7. int sz = strSend.size();
  8. send(m_socket, strSend.c_str(), sz, 0);
  9. }

Receiving Loop:
C++ Syntax (Toggle Plain Text)
  1. FD_SET setReader;
  2. FD_ZERO(&setReader);
  3. FD_SET(nClients[c].m_socket, &setReader);
  4. int n = nClients[c].m_socket + 1;
  5. if (select(n, &setReader, 0, 0, 0) != SOCKET_ERROR) {
  6.  
  7. char recvbuff[1024];
  8. int bytesRecv = 0;
  9.  
  10. // each socket
  11. bytesRecv = recv(nClients[c].m_socket, recvbuff, 1024, 0);
  12.  
  13. if (bytesRecv>0) {
  14. string strRecv = recvbuff;
  15. string output = strRecv.substr(0, bytesRecv);
  16.  
  17. cout << output << endl;
  18.  
  19. }
  20.  
  21. }

The select() doesn't seem to have any effect. Do any of you happen to have successful network code that fits into a loop like this, and doesn't stack messages, that I could look at? Thanks for all the help.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
Mr Violent is offline Offline
22 posts
since Mar 2005
May 5th, 2006
0

Re: Winsock C++ help: receiving data

stacking is not something unexpected or errornous in the socket API. the TCP IP protocol only guarantees that the data will reach the destination at the sent order. It may get sent in one try or multiple tries.The problem here is that you are using a 1024 size buffer. If the network IO buffer at the receiving end has data to fill this buffer it fills it with that data. The only way you can eliminate this problem is by using the knowledge of the properties of the data sent. If you know the length you can traverse the buffer using that length. Also you can use a buffer of exactly the required lenght.But even then if there isnot sufficient data, you may get a partially fileed buffer in one try and the rest of the data in the next. If you don't know the lenght, then you will have to use something like the line termination character when sending character data. This is the most reliable.
The best way to handle this problem is to use the 1024 size buffer for data collecting and process this data before displaying it.
Something like coding another loop to find the EOL character in the buffer, displaying the data upto that, and again searching for the EOL....
Moderator
Reputation Points: 572
Solved Threads: 115
Mentally Challenged Mod.
WolfPack is offline Offline
1,559 posts
since Jun 2005
May 5th, 2006
0

Re: Winsock C++ help: receiving data

That's not a bad idea at all--sending the EOL termination character and completely ignore the fact that packets may stack. However, I used a 1ms sleep on my client that was sending data to my server, and every message was seperated. My guess is that my client was sending too fast for send(), and the receiving was fine. I'm not sure what my limits are, but I may had to 'pad' my messages with a beginning and ending character to recognize the entirety of a message. Thanks for all the responses.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
Mr Violent is offline Offline
22 posts
since Mar 2005

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: Works with one, not more.
Next Thread in C++ Forum Timeline: reStructure of code: include 2 void functions





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC