🔒 Locked
Multiple asynchronous socket problems!
Advertisement
Original Post
Hi, I'm working on my first game using sockets but isn't going as good as I could hope for. First I used non-blocking sockets with a sepperate thread handling socket-receiving for the client and in the server one thread for accepting connections and one for handling messages sent by the clients. It worked but I had a lot of crashes and strange disconnect behaviors i couldn't fix so I decided to switch to asynchronous sockets. But since then... 1. When I start the server and client on the same computer it works fine to connect, but when I connect to a server on another computer the server cannot find the user from the userlist using the socket as id. The socket is added to that list on FD_CONNECT, what could have gone wrong? 2. Sometimes when the winsock message handler gets the FD_READ message and tries to read from the socket it just returns WSAEWOULDBLOCK. How can that happen??? I thought it could be because the socket was sending right then, but even if I loop the receive until some other error the loop will never end. This nevere happens when I step throught the application slowly in a debugger. It also seams that some messages never reaches the server/client eg. when the user fires multiple times. 3. Why does WSAGETSELECTERROR sometimes returns that the connection is reset? Should't these kind of events be handled by FD_CLOSE? Sorry for many spelling mistakes but I hope you'll understand most of it =)
I've checked it out but still haven't solved my problem.
I've been coding a test program and it seams that my send/recv code is bugged.
I get lots of "recv() error" messages when I try to receive data on FD_READ messages.
I've been coding a test program and it seams that my send/recv code is bugged.
void CSocket::SendData(char *message, unsigned long length){ if (status == 0) return; int bytes; unsigned long messageSize = length; int total_sent = 0; messageSize = htonl(messageSize); do { bytes = send(sock, (char *)&messageSize+total_sent, sizeof(messageSize)-total_sent, 0); if (bytes == SOCKET_ERROR) { /* if (WSAGetLastError() == WSAEWOULDBLOCK) { // Sleep(750); continue; } */ MessageBox(NULL, "send() error", "Error", MB_OK); return; } total_sent += bytes; } while (total_sent < sizeof(messageSize)); messageSize = ntohl(messageSize); total_sent = 0; do { bytes = send(sock, message+total_sent, length-total_sent, 0); if (bytes == SOCKET_ERROR) { /* if (WSAGetLastError() == WSAEWOULDBLOCK) { // Sleep(750); continue; } */ MessageBox(NULL, "send() error", "Error", MB_OK); return; } total_sent += bytes; } while (total_sent < (int) messageSize);}int CSocket::GetData(char* dest){ if (status == 0) return 0; int bytes; unsigned int messageSize; int total_recv = 0; do { bytes = recv(sock, (char *)&messageSize+total_recv, sizeof(messageSize)-total_recv, 0); if (bytes == SOCKET_ERROR) { /* if (WSAGetLastError() == WSAEWOULDBLOCK) { Sleep(750); continue; } */ MessageBox(NULL, "recv() error", "Error", MB_OK); return 0; } if (bytes == 0) return 0; total_recv += bytes; } while (total_recv < sizeof(messageSize)); messageSize = ntohl(messageSize); total_recv = 0; do { bytes = recv(sock, (dest+total_recv), (messageSize-total_recv), 0); if (bytes == SOCKET_ERROR) {/* if (WSAGetLastError() == WSAEWOULDBLOCK) { Sleep(750); continue; }*/ MessageBox(NULL, "recv() error", "Error", MB_OK); return 0; } if (bytes == 0) return 0; assert(total_recv != messageSize); total_recv += bytes; } while (total_recv < (int) messageSize); return bytes;I get lots of "recv() error" messages when I try to receive data on FD_READ messages.
I havent tries that yet, but I suppose its the WSAEWOULDBLOCK error since when I un-comment the WSAEWUOULDBLOCK error-check the program gets stuck in a never-ending loop.
As far as I've understood WSAEWOULDBLOCK is returned when you are trying to recv() from a socket that has nothing new to receive. But I'm calling the CSocket::GetData(...) on FD_READ messages, so I cannot understand whats the problem... I'm not 100% on this, but I think when I send a message from the client to the server, the server first pop-up an error message and then receives the real message. So is the FD_READ sent 2 times of which one is wrong?
Now while writing this it suddenly appeared to me that this might be because I first send the message size and then the buffer. Is this is? So if i merged the data to one buffer this problem will be solved...?
As far as I've understood WSAEWOULDBLOCK is returned when you are trying to recv() from a socket that has nothing new to receive. But I'm calling the CSocket::GetData(...) on FD_READ messages, so I cannot understand whats the problem... I'm not 100% on this, but I think when I send a message from the client to the server, the server first pop-up an error message and then receives the real message. So is the FD_READ sent 2 times of which one is wrong?
Now while writing this it suddenly appeared to me that this might be because I first send the message size and then the buffer. Is this is? So if i merged the data to one buffer this problem will be solved...?
I've been testing a little now - changing some code. Instantly after using the recv() the server receives another FD_READ message but when the program tries to receive from the socket it returns 0 bytes. Doesn't 0 bytes mean the user disconnected? Is this normal behavior for async sockets (=I should just ignore 0 bytes received)?
If the socket is non-blocking, it can return 0 bytes when you try to read. I don't know the async socket API well enough to know if it does something similar. Are you also setting your socket as non-blocking, perchance?
What if you just treat the WOULDBLOCK error as "everything's OK" and do nothing, just returning to your regular business? Will you get an infinite stream of FD_READ messages? If not, I'd just accept the getting of 0 bytes and be happy. If you get an endless stream of messages, then either you're reading the wrong socket, or you're using the API wrong (wild guess that's probably wrong: perhaps async sockets will treat a non-blocking socket as always readable, and always send FD_READ messsages?)
What if you just treat the WOULDBLOCK error as "everything's OK" and do nothing, just returning to your regular business? Will you get an infinite stream of FD_READ messages? If not, I'd just accept the getting of 0 bytes and be happy. If you get an endless stream of messages, then either you're reading the wrong socket, or you're using the API wrong (wild guess that's probably wrong: perhaps async sockets will treat a non-blocking socket as always readable, and always send FD_READ messsages?)
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement