Winsock Deadlock
I have been trying to make a small multithreaded winsock server and client to send data to each other, but I have run into a slight design problem. The setup i have now is that the server has two threads. One thread for recieving data from the client, and one for sending data to the client. The problem with this setup is that it seems to just stop the server from doing anything. I have stepped into it with the debugger and it seems as though the server thread that waits for incoming messages from the client is stopping the server from using the send winsock function to the client. Presumably recv locks the socket so that send cannot use it? The result of all this is that nothing gets sent to the client, and so the client nver responds to anything, and so it gets stuck in recv for ever. Does this sound like a possible course of events? What are the best ways around this? Im using winsock2, and a console based server.
-keyboard
Winsock is BLOCKING, that is, it waits until it can do whatever you want it to do, before doing it. Use asyncronous sockets, or use select(). With Asyncronous sockets, create a message only window (specify HWND_MESSAGE) as the parent window in CreateWindow/CWEx, and then call WSAAsyncSelect. If you're still in the dark about what's happening, email me at kawahee@gmail.com, and I'll send you my winsock 2 wrapper.
I was aware that winsock is blocking, which is why i was trying to use threads. That way it would only block the relevant thread. For example, i would call recv on a socket in one thread, blocking that thread, but still carry on sending data through the same socket with another thread.
The problem i seem to have run into is that you do not seem to be able to send data to a socket on a seperate thread with the send function when another thread is blocking due to a call to recv that hasnt unblocked yet. Instead of the send thread just sending the data through the socket, it blocks the thread. This means that both threads are blocked, and the server does nothing.
I don't think I can use async sockets in a console application can I?
Perhaps a better solution would be to use two sockets, one for sending and one for recieving. That way the two threads shouldn't interfere with each other and cause the server to block.
Has anybody else designed a multithreaded winsock server before without using async sockets? Are there any other options?
Thanks
The problem i seem to have run into is that you do not seem to be able to send data to a socket on a seperate thread with the send function when another thread is blocking due to a call to recv that hasnt unblocked yet. Instead of the send thread just sending the data through the socket, it blocks the thread. This means that both threads are blocked, and the server does nothing.
I don't think I can use async sockets in a console application can I?
Perhaps a better solution would be to use two sockets, one for sending and one for recieving. That way the two threads shouldn't interfere with each other and cause the server to block.
Has anybody else designed a multithreaded winsock server before without using async sockets? Are there any other options?
Thanks
-keyboard
Oops. Anonymous Postageage. All comments for the above post should go to me.
Your receive thread should not be blocking on recv(), you should instead be blocking on select() if you must block and must use threads this way.
If your target operating system is Windows 2000+ however, I recommend using IOCP. It's a little harder to setup, but inifinitely more scalable.
BindIoCompletionCallback() is a good place to start. Windows takes care of setting up all the threading and pools and all you have to do is wrap the OVERLAPPED struct into a class of your choice.
Robert
If your target operating system is Windows 2000+ however, I recommend using IOCP. It's a little harder to setup, but inifinitely more scalable.
BindIoCompletionCallback() is a good place to start. Windows takes care of setting up all the threading and pools and all you have to do is wrap the OVERLAPPED struct into a class of your choice.
Robert
Quote:How do you mean it's stopping the server from using the send function? You mean the server blocks on send()? Does the client receive any messages from the server?
... it seems as though the server thread that waits for incoming messages from the client is stopping the server from using the send winsock function to the client
Yes it blocks on the send(), and the client does not recieve anything.
-keyboard
Why not use events?
And only call recv when there actually is a message to be received. So you have the receiving thread blocked on waiting for the event instead of recv.
Regards,
/Omid
And only call recv when there actually is a message to be received. So you have the receiving thread blocked on waiting for the event instead of recv.
Regards,
/Omid
Best regards, Omid
When send() blocks it means that the message does not fit in the send buffer of the socket. The buffers of a socket can be thought of like share memory spaces accessable by both ends of the connection. The send buffer of your server is the receive buffer of your client, and vice versa. You can set the size of socket buffers with:
int sendWindowSize = SEND_BUFFER_SIZE;
setsockopt(socketHandle, SOL_SOCKET, SO_SNDBUF, (char*)&sendWindowSize, sizeof(sendWindowSize));
...use SO_RCVBUF for receive buffer.
So your send() should not block forever. If the client receives data at a similar rate to what the server is sending, send() rarely blocks at all. The usual case it does happen that I've noticed is when the sender is say broadband, and the receiver is dialup 56k or something, and I'm transfering a sizeable amount of data. This could be thought of as the buffer being a bucket of water - the sender is filling it up with a fire hose at the top, and the receiver is draining it with a tiny hole at the bottom.
I would take a closer look at what is happening on the client end.
int sendWindowSize = SEND_BUFFER_SIZE;
setsockopt(socketHandle, SOL_SOCKET, SO_SNDBUF, (char*)&sendWindowSize, sizeof(sendWindowSize));
...use SO_RCVBUF for receive buffer.
So your send() should not block forever. If the client receives data at a similar rate to what the server is sending, send() rarely blocks at all. The usual case it does happen that I've noticed is when the sender is say broadband, and the receiver is dialup 56k or something, and I'm transfering a sizeable amount of data. This could be thought of as the buffer being a bucket of water - the sender is filling it up with a fire hose at the top, and the receiver is draining it with a tiny hole at the bottom.
I would take a closer look at what is happening on the client end.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement