• Advertisement
Sign in to follow this  

Help, non-blocking sockets.

This topic is 3302 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

Hello there :) I'm having lots of trouble making a non-blocking winsock program(win32 console application.) I have a little project that is working(blocking mode.) I would be glad if you could have a look and see if you can give me a hint, tips och anything to point me in the right direction. Project download link: http://thuski.se/ixuz/projekt/winsock.rar My goal is to make a fun multiplayer iceclimbers game before 11-03-2009 for a lan event. Feel free to check out the website too http://www.ntilan.se/ Thanks! // ixuz

Share this post


Link to post
Share on other sites
Advertisement
I have not looked at your code, but I might give you some advice anyways.
I suggest that you use 2 threads when using sockets. 1 listening thread, and 1 sending thread.
Add items you want to send in a Send queue, and let the sender thread send items from that queue.
Same goes for the listening thread.
Remember to properly lock the send/receive queue's when adding/removing items from them.


Share this post


Link to post
Share on other sites
I am in the process of creating a Winsock tutorial site.

I have actually covered a tutorial non-blocking sockets on my programming site (both client and server). You are welcome to take a look. Feel free to comment and critique. :)

www.win32developer.com

Share this post


Link to post
Share on other sites
I've acually succeded in make a non-blocking server and a non-blocking client now yay. But now another problem pops up, I can't get more than one client connected at the same time. How do you store multiple clients? I've been thinking of something like this, accepting a client then store it in a vector for later use.

If you'd like to have a look at my source code you can find it here:
http://thuski.se/ixuz/projekt/winsock2.rar

Thanks // ixuz

Share this post


Link to post
Share on other sites
Quote:
Original post by ixuz
I've acually succeded in make a non-blocking server and a non-blocking client now yay. But now another problem pops up, I can't get more than one client connected at the same time. How do you store multiple clients? I've been thinking of something like this, accepting a client then store it in a vector for later use.
Yup, exactly.

Share this post


Link to post
Share on other sites
Yay, it worked out really nice! I can wait for two clients to connect to the server, they both can send/recv from the server(non-blocking). :)

How can I accept connecting clients while my server is running, I have done it like this for now:
Quote:

void ServerSocket::StartHosting( int port )
{
Bind( port );
Listen(); // blocking and awaiting client
Listen(); // blocking and awaiting client again
}

void ServerSocket::Listen() {
//cout << "LISTEN FOR CLIENT..." << endl;
listen ( mySocket, 2 );

acceptSocket = accept( myBackup, NULL, NULL );
while ( acceptSocket == SOCKET_ERROR )
{
acceptSocket = accept( myBackup, NULL, NULL );
}
mySocket = acceptSocket;

unsigned long a[1];
ioctlsocket(mySocket, FIONBIO, a);
acceptedSockets.push_back( mySocket );

cout << "CONNECTION ACCEPTED" << endl;
}

The program will wait for exact two clients to connect then it continues.

How can I make my accepting function work calling without blocking mode?
Would it work to call the accept function every frame to possibly accept new clients?
Am I supposed to call the select() function before accept() function? if so how do I use select() properly? :)

Thanks // ixuz :D

[Edited by - ixuz on January 23, 2009 1:49:53 PM]

Share this post


Link to post
Share on other sites
Quote:
Would it work to call the accept function every frame to possibly accept new clients?


Yes.

Regarding select(): You EITHER use non-blocking sockets, OR select, not both.

With select(), you send in a set of sockets. Select will tell you which of those sockets you can receive on, or send on, without blocking.

After select(), you walk the set that comes back, and call recv() or send() on those sockets, once each. Because they came back from select() as available, it is guaranteed that your call will not block for the first call to each socket. Of course, there may not be as much data as you want there -- recv() may return just one byte, or send() may be able to send just one byte -- but you are guaranteed to make progress.

Share this post


Link to post
Share on other sites
Don't believe hplus0603. You need to use non-blocking sockets when you use i/o multiplexing (select, poll, epoll ...). Otherwise it can happen that recv/send blocks.

Share this post


Link to post
Share on other sites
Quote:
Original post by imgty

Otherwise it can happen that recv/send blocks.


If properly implemented, this should not happen.

Quote:
For connection-oriented sockets (type SOCK_STREAM for example), calling recv will return as much data as is currently available—up to the size of the buffer specified


It will block only if there is no data available in the buffer. select() determines which sockets have at least some data available. But the important thing is to call send/recv/accept only once per select() call, and only on descriptors returned in corresponding set.

Share this post


Link to post
Share on other sites
Ok, for recv on a tcp socket that might never happen. On a UDP socket a packet could be dropped theoretically between the call to select and the receive function.

But...
send on a socket in blocking mode blocks until the *whole* buffer has been consumed. At least on Windows. It might be different on other operating systems.

Share this post


Link to post
Share on other sites
Quote:
On a UDP socket a packet could be dropped theoretically between the call to select and the receive function.


No, it could not. The packet has left the network, and is in the realm of the kernel. The guarantees of select() and recv() say that the packet cannot be dropped at that point.

Quote:
But...
send on a socket in blocking mode blocks until the *whole* buffer has been consumed. At least on Windows. It might be different on other operating systems.


No, it does not, if select() says that the socket is writable, then a send() on that socket will not block. If that means that only half the buffer is consumed (on a TCP stream), then only half the buffer is consumed (and the amount consumed is returned).

Share this post


Link to post
Share on other sites
Hi, I acually managed it to work with non-blocking and select. I had problem accepting new clients, now my select() function tells me if a client wants to connect.

How about disconnects, should I ping all my clients all the time? Could anyone write down some pseudo code for your solution?

And thanks alot to all of you answering my questions, thank you!

// ixuz

Share this post


Link to post
Share on other sites
@hplus0603

Ok, you are right for the receive functions (and accept). select gives this guarantee:
Quote:
If the socket is currently in the listen state, it will be marked as readable if an incoming connection request has been received such that an accept is guaranteed to complete without blocking. For other sockets, readability means that queued data is available for reading such that a call to recv, WSARecv, WSARecvFrom, or recvfrom is guaranteed not to block.


But you are wrong for the send functions:
Quote:
If the socket is not processing a connect call, writability means a send, sendto, or WSASendto are guaranteed to *succeed*. However, they can block on a blocking socket if the len parameter exceeds the amount of outgoing system buffer space available.

Share this post


Link to post
Share on other sites
Trivia:

If you select() a socket for reading, and it returns that there is data available, but reading results in zero bytes read, this means...

Share this post


Link to post
Share on other sites
Well, I figured you'd know the answer, being a moderator :)

It actually also turns out that with poll(), the ONLY sure way that you can tell (cross-platform) if a socket is closed is if it returns 0 bytes on a read, after poll claims it is readable.

Share this post


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

  • Advertisement