Jump to content
  • Advertisement
Sign in to follow this  
quant

Winsock Deadlock

This topic is 4867 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by quant
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?


Yes, you can. Win32 Console applications can still call WinAPI/WinSock functions, such as the WSA* calls. Unix-based applications can use select() and anychronous calls.

Quote:
Original post by quant
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.

Surely if you have two sockets on the server sides, you would need two sockets on the client side? It's probably not worth complicating things.

Quote:
Original post by quant
Has anybody else designed a multithreaded winsock server before without using async sockets? Are there any other options?

Thanks

I've written an IRC using a multi-threaded approach. I'd probably prefer to do it that way again. [caution] Adding more threads makes thread synchronization more difficult [caution], but if you're writing a server you may want to program in multi-threaded fashion in order to get more power out of dual processing systems.



I don't know if this is actually allowed, and I hadn't thought much about it until now, but I've just realised I am doing the same thing you are doing - manipulating the sockets in more than one thread. So, one thread would be recv()ing from the socket, whilst another thread would be send()ing pings and channel messages and the like. It seems to work for me. [wink]

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
Quote:
... 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
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?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!