Click to See Complete Forum and Search --> : How to get past a recv() ?
BlackSun
December 15th, 2004, 11:08 AM
ok, newbie question here, but in my app I have a simple foreverloop that goes something like this
SOCKET sock;
// All initiations for the socket ...
char buffer[1000];
while (true)
{
int i = recv(sock, buffer, sizeof(buffer), 0);
buffer[i] = '\0';
if (i > 1)
{
/7 Do something really useful, if I ever would get in here ...
}
}
Now the problem is, I never get to the if-statement unless the app receives something, so how can this be fixed ?
TIA
BlackSun
Andreas Masur
December 15th, 2004, 11:59 AM
You can use 'select()' to determine whether there is something to receive...
int Receive(SOCKET Socket, void *pvBuffer, int iStillToReceive)
{
int iRC = 0;
int iReceiveStatus = 0;
timeval ReceiveTimeout;
char *pBuffer = static_cast<char *>(pvBuffer);
// Set timeout
ReceiveTimeout.tv_sec = 0;
ReceiveTimeout.tv_usec = 250000; // 250 ms
fd_set fds;
FD_ZERO(&fds);
FD_SET(Socket, &fds);
// As long as we need to receive bytes...
while(iStillToReceive > 0)
{
iRC = select(0, &fds, NULL, NULL, &ReceiveTimeout);
// Timeout
if(!iRC)
return -1;
// Error
if(iRC < 0)
return WSAGetLastError();
// Receive some bytes
iReceiveStatus = recv(Socket, pBuffer, iStillToReceive, 0);
// Error
if(iReceiveStatus < 0)
return WSAGetLastError();
else
{
// Update buffer and counter
iStillToReceive -= iReceiveStatus;
pBuffer += iReceiveStatus;
}
}
return 0;
}
Mathew Joy
December 15th, 2004, 12:34 PM
Now the problem is, I never get to the if-statement unless the app receives something, so how can this be fixed ?This is because your recv() initiates a blocking call: your socket is in the blocking mode. There are lots of ways to get overcome this and are discussed quite a few times in this forum. One method is select, as Andreas said. For others you can do a simple search in this forum. Post if you have specific doubts. :thumb:
BlackSun
December 15th, 2004, 02:32 PM
Ok, thanks !
Just one dumb question...
Whats iStillToReceive in your funvtion ? I don't get how I should know what to pass there ...
drewdaman
December 15th, 2004, 03:50 PM
just something to add to what the gurus said :)
you can also use setsockopt and set a timeout for recv if you are using blocking sockets ..
Mathew Joy
December 15th, 2004, 10:59 PM
From the funtion's point of view, it is the number of bytes you expect to receive from the remote end of the connection. This function does not return till you get the iStillToReceive no of bytes - unless there is a timeout, socket closure or an error. From the recv()'s point of view, you are telling the size of the buffer that has been submitted to receive data. For more info on recv(), look at the following faq..
When does 'recv()' return? (http://www.codeguru.com/forum/showthread.php?t=303078)
BlackSun
December 16th, 2004, 03:06 AM
Ok, thanks everyone so far. Guess I'll be back very soon with more annoying questions..
Andreas Masur
December 16th, 2004, 03:33 AM
you can also use setsockopt and set a timeout for recv if you are using blocking sockets ..
Note that this is only available in the winsock 2 implementation... :cool:
Mathew Joy
December 16th, 2004, 12:54 PM
Ok, thanks everyone so far. Guess I'll be back very soon with more annoying questions..
Usually it is the post that is annoying rather than the questions... :cool:
BlackSun
December 16th, 2004, 01:08 PM
Oh boy.. do I feel stupid, doesn't seem I do anything else but run into problems..
1. I can't even find that select function on msdn.
2. Is there anything similar to do for an Accept call ? Or is it just plain stupid to do it like this ?
3. Is this a acceptable way to go about it ? I know I may be losing some messages if traffic is high, but there wont be so much traffic...
//nPeople is just an in that keeps track of number of peoples connected
//clientsocket[5] are the sockets
// The vars in the accept are just to get connectep ...
while(true)
{
// Inits and so on
if ( nPeople < 5)
{
if(clientsocket[nPeople] = accept(main_socket, (sockaddr*)&client_addr, &cli_len))
{
// Do whatever has to be done
nPeople++;
}
}
// problem 3, want to get all incoming messages
for (int l = 0; l < nPeople ; l++)
{
i = recv(clientsocket[l], buffer, sizeof(buffer), 0);
buffer[i] = '\0';
if (i)
break;
}
}
drewdaman
December 16th, 2004, 01:52 PM
Oh boy.. do I feel stupid, doesn't seem I do anything else but run into problems..
1. I can't even find that select function on msdn.
use other sources? i don't like msdn to start with! to verbose! lol..
http://www.gamedev.net/reference/articles/article1494.asp
http://www.scit.wlv.ac.uk/~jphb/comms/sockets.html#select
http://www.lowtek.com/sockets/select.html
if you are interested in using timeouts (and are using winsock2 as pointed out earlier), look at the following code from http://www.intel.com/cd/ids/developer/asmo-na/eng/76431.htm?page=7 :
//UDP Example w/timeout
#include <winsock2.h>
WSAStartup()
gethostbyname() //Get IP address from host name
socket()
int t = 10000; //10 sec
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *) &t, sizeof(t))
while ("work to do")
{
sendto()
rv = recvfrom()
if (rv == SOCKET_ERROR) {
if (WSAETIMEDOUT == WSAGetLastError())
//recvfrom has timed out
}
}
closesocket()
WSACleanup()
BlackSun
December 16th, 2004, 07:03 PM
Ok, thanks for the links. So some questions after reading a little. If I go with select, and I discover that there is som traffic soming in, and I start accepring it, how can I then be sure that it is a connect cal ? Couldn't it just be some other data coming in, and then accept() would still block my loop ?
So, is there any way of detecting if the incoming data is a connect request ?
Mathew Joy
December 18th, 2004, 12:42 AM
1. I can't even find that select function on msdn.
It is quite odd. If you don't have a local version of msdn in your hard disk, it is high time that you get it. All other materials should be a suppliment to MSDN not an alternative to.
2. Is there anything similar to do for an Accept call ? Or is it just plain stupid to do it like this ?I don't get what you mean. But looking into a few threads that you posted I think you need to spend some time with the material to have a first hand knowledge of the underlying principles and the function that use it to acheive the purpose. You have MSDN, search the web, look at codeguru faq and have a look at this forum to see some of techniques discussed.
3. Is this a acceptable way to go about it ? I know I may be losing some messages if traffic is high, but there wont be so much traffic... My answer to the #2 holds for this post too. The basic principle is, when you are using TCP you are not sending as messages, rather as stream of data. The difference is message have message boundary while stream doesn't. That's why there is a isStillToReceive parameter in the above posted function. Another thing: there is no question of loosing a single byte of your data.
So spend some time to learn and come back with your qestions.
Good Luck :thumb:
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.