views:

241

answers:

3

I'm hoping someone can explain a situation -- any situation -- in which a non-blocking Windows socket would not immediately return after using send() on it. On other platforms, my code works as intended, so it appears to be a Windows-specific issue.

The way I can tell it isn't returning is quite simple: I cout a message immediately before and after the send() function, and upon running, the console only shows the first message. I can't seem to reproduce it in a simplified example, so I apologize for the lack of code. I will try to provide more specifics if necessary.

Edit:

The specific code where the socket is created and set as non-blocking is the following. I'm assuming that there is indeed no way a non-blocking socket would behave this way, and that something else is causing it to stop before the second message is shown. Thank you for your help anyway...I will try my best to get to the bottom of it, but right now I'm quite mystified.

SOCKET new_sock = accept(sock, (struct sockaddr*)&addr, &addr_size);

#ifdef _WIN32
    unsigned long ul;
    ioctlsocket(new_sock, FIONBIO, &ul);
#else
    fcntl(new_sock,F_SETFL,O_NONBLOCK);
#endif

setsockopt(new_sock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg));
setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int));
+1  A: 

If your "cout" message display does not contain an std::endl, the call might not be blocking without you noticing !

Benoît
I actually do use std::endl in both messages but thank you for the suggestion.
Tadpole
Ok. That was my first guess, sorry ! Why don't you use boost.asio ? I'd be more able to help you (and others too, i think)
Benoît
I'd like to use Boost.Asio, but to do so I'd have to assign a native socket to an ip::tcp::socket object, which mysteriously never works...it always throws this error: "The parameter is incorrect." This problem was mentioned, but not solved, here: http://stackoverflow.com/questions/1712641/boost-asio-documentation-is-non-existent-what-do-these-errors-mean
Tadpole
Why would you want to create a native socket independently from boost.asio ?
Benoît
I'm actually using a SOCKS proxy library as part of my program, so unless I convert the entire library to use Boost, I would have to use the assign() function to convert the sockets it gives me to Boost sockets.
Tadpole
Could the problem be in the SOCKS library? I understand that SOCKS libraries often override the "vanilla" socket-APIs. It seems likely to be the case that your SOCKS library isn't implementing non-blocking sockets correctly, or it expects some other way of setting the socket to be non-blocking...
Aidan Cully
+1  A: 

Send will block on filling the ip stack buffers on a connected socket. If you have a connected socket and you start throwing data at it faster then the ip stack can roll it out the wire with the attendant ack nak paddywacks then the send will block.

I have not seen that properly set non blocking sends will block though. They will error with wouldblock. So I would look to how you are setting non blocking io. Are you sure you are setting non blocking on the resultant socket not the base socket... ie the socket returned from the accept.

Slaftos
I added the code in question to the parent post if it helps at all.
Tadpole
A: 

if this is the actual code, you havn't initialized ul . Do:

unsigned long ul = 1;
ioctlsocket(new_sock, FIONBIO, &ul);
nos
I tried it but it doesn't change the behavior at all. In fact I think ioctlsocket will make it non-blocking so long as it isn't equal to 0.
Tadpole
right. and when you didn't initialize originally it could have been 0. or 1. or any kind of garbage. Check the return value of ioctlsocet as well so you're sure it doesn't fail for whatever reason.
nos
Yep I just checked...it returns 0 so it's successful.
Tadpole