Probleme with WSAWaitForMultipleEvents
Hi :) I would like to know if WSAWaitForMultipleEvents just wait for new event or also use a queue for all unread event. I say that because when I send two message to a client in a short laps of time, if the managing of the first one is not finish before receiving the second, the next call to WSAWaitForMultipleEvents not give the second message .
If you're using TCP, chances are that you get signaled for both messages together (because of TCP packet coalescing). Look in the Forum FAQ for how to packetize separate messages over TCP. You also need to read all you can out of the socket each time the event is signalled, to make sure you don't leave something there and then block forever.
enum Bool { True, False, FileNotFound };
Thanks for the reply :)
Yes, I am using TCP
I have seen that your advise is to send the lenght of the message before sending it (because it can be split or be fusioned with another).
Acutaly, I use getsockopt for getting the size of the buffer : Bad idea ?
[edit] You're all right, I received all message in the same time [/edit]
So, instead of that :
[sender]
send( socket, (char*)data, bufferSize, 0 );
[receiver]
DWORD bufferSize;
int dwordSize = sizeof(bufferSize)
char* buffer;
char* data;
getsockopt( connection->m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&(bufferSize), &dwordSize );
buffer = new char[bufferSize];
bufferSize = recv( connection->m_socket, buffer, bufferSize, 0);
data = new char[bufferSize];
memcpy( data, buffer, bufferSize);
I will have something like that :
[sender]
send( socket, htons( (u_short)bufferSize ), sizeof(u_short), 0 );
send( socket, (char*)data, bufferSize, 0 );
[receiver]
char* buffer;
u_short bufferSize;
int bufferSizeInt;
int byteRcved=0;
recv( connection->m_socket, bufferSize, sizeof(u_short), 0);
bufferSizeInt = (int)htons(bufferSize);
buffer = new char[bufferSizeInt];
while( byteRcved < bufferSizeInt )
{
byteRcved += recv( connection->m_socket, buffer+byteRcved , bufferSizeInt-byteRcved , 0)
}
data = new char[bufferSizeInt ];
memcpy( data, buffer, bufferSize)
But I don't understand how to read all I can from the socket.
With this algorithme, I only will receive the first message. I can't try to receive another size indicator, because if it is the last message, this will block the thread for other messages
-----------------------------------------------------------------
(here is my actual code)
[Edited by - Ruffi on December 5, 2005 10:51:37 PM]
Yes, I am using TCP
I have seen that your advise is to send the lenght of the message before sending it (because it can be split or be fusioned with another).
Acutaly, I use getsockopt for getting the size of the buffer : Bad idea ?
[edit] You're all right, I received all message in the same time [/edit]
So, instead of that :
[sender]
send( socket, (char*)data, bufferSize, 0 );
[receiver]
DWORD bufferSize;
int dwordSize = sizeof(bufferSize)
char* buffer;
char* data;
getsockopt( connection->m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&(bufferSize), &dwordSize );
buffer = new char[bufferSize];
bufferSize = recv( connection->m_socket, buffer, bufferSize, 0);
data = new char[bufferSize];
memcpy( data, buffer, bufferSize);
I will have something like that :
[sender]
send( socket, htons( (u_short)bufferSize ), sizeof(u_short), 0 );
send( socket, (char*)data, bufferSize, 0 );
[receiver]
char* buffer;
u_short bufferSize;
int bufferSizeInt;
int byteRcved=0;
recv( connection->m_socket, bufferSize, sizeof(u_short), 0);
bufferSizeInt = (int)htons(bufferSize);
buffer = new char[bufferSizeInt];
while( byteRcved < bufferSizeInt )
{
byteRcved += recv( connection->m_socket, buffer+byteRcved , bufferSizeInt-byteRcved , 0)
}
data = new char[bufferSizeInt ];
memcpy( data, buffer, bufferSize)
But I don't understand how to read all I can from the socket.
With this algorithme, I only will receive the first message. I can't try to receive another size indicator, because if it is the last message, this will block the thread for other messages
-----------------------------------------------------------------
(here is my actual code)
void WINAPI cConnection::getMessages( cConnection* connection ){ HANDLE eventsArray[2]; bool stopThread = false; DWORD result; WSANETWORKEVENTS info; while( !stopThread ) { eventsArray[0] = connection->m_hStopThread; eventsArray[1] = connection->m_event; // wait for an event result = WSAWaitForMultipleEvents( 2, eventsArray, FALSE, WSA_INFINITE, FALSE ); switch(result) { // m_hStopThread -> we finish the thread case WSA_WAIT_EVENT_0 : stopThread = true; break; // message from the server case WSA_WAIT_EVENT_0+1 : // get information about this event WSAEnumNetworkEvents( connection->m_socket, connection->m_event, &info ); switch(info.lNetworkEvents) { // server connection closed case FD_CLOSE: // server close ! WaitForSingleObject( connection->m_hMutex, INFINITE ); connection->m_connected = false; ReleaseMutex( connection->m_hMutex ); break; case FD_READ: char* buffer; void* data; DWORD bufferSize; int dwordSize = sizeof(bufferSize); // get the size of the buffer getsockopt( connection->m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&(bufferSize), &dwordSize ); buffer = new char[bufferSize]; if( (bufferSize = recv( connection->m_socket, buffer, bufferSize, 0)) == SOCKET_ERROR ) break; // TODO -> managing the error // copy the data data = new char[bufferSize]; memcpy( data, buffer, bufferSize); delete [] buffer; WaitForSingleObject( connection->m_hMutex, INFINITE ); connection->processMessage( data, bufferSize ); ReleaseMutex( connection->m_hMutex ); delete [] data; break; } // switch(info.lNetworkEvents) break; // case WSA_WAIT_EVENT_0+1 } // switch(result) } // while( !stopThread )}
bool cServer::sendData( SOCKET socket, void* data, int bufferSize ){ if( send( socket, (char*)data, bufferSize, 0 ) == SOCKET_ERROR ) return false; return true; }
[Edited by - Ruffi on December 5, 2005 10:51:37 PM]
Quote:
Original post by Ruffi
But I don't understand how to read all I can from the socket.
With this algorithme, I only will receive the first message. I can't try to receive another size indicator, because if it is the last message, this will block the thread for other messages
Use a stateful receive buffer, and decouple message receiving from message processing. Like so:
On message m received from client c: While m is not empty: If an incomplete packet p, from client c is in progress: fill p with data taken from c, but no more than needed to complete p If p is complete: pass p off to processing layer mark client c as not having a packet in progress Else: read length of packet using data taken from c start incomplete (empty) packet p for client c
Basically, you keep around fragments until they're complete, and then you process them.
Hi tried to do like you said.
But I have a probleme : I send the size of the message and I send its data, by two differents call of send(). The first succed, but the second failed (return SOCKET_ERROR )
In the reception, the first call of recv(), to get the lenght of the message, fail (return -1).
This is how I send the message (server side)
This is how I receive the message (client side)
[Edited by - Ruffi on December 5, 2005 11:54:34 PM]
But I have a probleme : I send the size of the message and I send its data, by two differents call of send(). The first succed, but the second failed (return SOCKET_ERROR )
In the reception, the first call of recv(), to get the lenght of the message, fail (return -1).
This is how I send the message (server side)
bool cServer::sendData( SOCKET socket, void* data, int bufferSize ){ u_short size = htons( (u_short)bufferSize ); if( send( socket, (char*)&size, sizeof(u_short), 0 ) == SOCKET_ERROR ) return false; if( send( socket, (char*)data, bufferSize, 0 ) == SOCKET_ERROR )// it fail here return false; return true; }
This is how I receive the message (client side)
case FD_READ:{ DWORD messageSize; int dwordSize = sizeof(messageSize); u_short bufferSizeTmp = 0; int messageRead = 0; int byteToReceive; char* buffer; int byteRcved; // get the size of all messages getsockopt( connection->m_socket, SOL_SOCKET, SO_RCVBUF, (char*)&(messageSize), &dwordSize ); // while all hasn't been all read while( messageRead < (int)messageSize ) { // get the size of the message messageRead += recv( connection->m_socket, (char*)bufferSizeTmp, sizeof(u_short), 0);// failed here : messageRead = -1, bufferSizeTmp = 0 byteToReceive = (int)ntohs(bufferSizeTmp); buffer = new char[ byteToReceive ]; byteRcved = 0; // get the message while( byteRcved < byteToReceive ) { int size = recv( connection->m_socket, buffer+byteRcved , byteToReceive-byteRcved , 0); if( size > 0) { messageRead += size; byteRcved += size; } } // process the message WaitForSingleObject( connection->m_hMutex, INFINITE ); connection->processMessage( buffer, byteToReceive ); ReleaseMutex( connection->m_hMutex ); delete [] buffer; }}
[Edited by - Ruffi on December 5, 2005 11:54:34 PM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement