Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[oft] from blocking to nonblocking server

79 views
Skip to first unread message

fir

unread,
Dec 5, 2017, 11:33:46 AM12/5/17
to
his is offtopic but maybe someone here will/would know

i dont like to read a weeks on tcp and sockets as this is a lot and confusing
(i prefer this time to spend on c/graphics etc)

i got some old tcp-server (on winapi winsock2) code, that worked but it was
not tested/inspected for being ok and was yet only working in blocking mode

the code goes

int SetupBlockingWinsockServer()
{

WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

/// Creating socket

servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

SOCKADDR_IN sin;
sin.sin_family = PF_INET;
sin.sin_port = htons(1111);
sin.sin_addr.s_addr = INADDR_ANY;

//bind

int retVal = bind(servSock, (LPSOCKADDR)&sin, sizeof(sin));

/// Trying to listen socket

retVal = listen(servSock, 10);

// Waiting for a client

ServClientSock = accept(servSock, NULL, NULL); return 1;


}

(i skipped the few lines of retvalue checking for errors for clarity)

my goal is just to turn it to non blocking without a lot of work but i would like to know this is ok

i checked experimentally via message boxes that it "blocks" on accept call
(block may be euphemism a bit here as it hang real hard, when no client is run then not only hourglass-pointer is shown, not only app gets fully unresponsible and non redraws itself but even closing it form task manager is hard, its possible but takes few seconds to kill)

what i did :

i added some line thet is supposed to set socked as nonblocked and move accept to separate function which i call then periodically (from run frame event)

int SetupBlockingWinsockServer()
{

WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);

/// Creating socket

servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

SOCKADDR_IN sin;
sin.sin_family = PF_INET;
sin.sin_port = htons(1111);
sin.sin_addr.s_addr = INADDR_ANY;

//bind

int retVal = bind(servSock, (LPSOCKADDR)&sin, sizeof(sin));

/// Trying to listen socket

retVal = listen(servSock, 10);

// set no blocking

u_long no_block=1;
ioctlsocket(servSock,FIONBIO,&no_block);

}

int WaitForClientAccept()
{
/// Waiting for a client

ServClientSock = accept(servSock, NULL, NULL);

if(ServClientSock == INVALID_SOCKET) return 0;


u_long no_block=1;
ioctlsocket(ServClientSock,FIONBIO,&no_block);
return 1;

}

this last one is as i said run periodically on server app frame and when it return 1 (it means it gett accepted connection?) i flag out both server code to not call it more and
client not to send more connections

it seem to work but as this is my
own slight experimentation only i would like to get pproval/confirmation
that this is in fact ok

is this ok or is there something wrong with it?

(btw as a side questions, do i need those flaging out here, or if i connected i could not bother for flaging out more sendings for connections and checks for incomming connections? (i know it would be wastefull maybe to send it still 50 times a second after connection was accepted but besides this waste would it work? (if that would be work maybe sending it once a second would work as
automatic connection reboval when something would get disconnected?)

tnx for answer if someone know whats goin on in that sockets/winsock, i got not much time for that

(fir)

Fred.Zwarts

unread,
Dec 6, 2017, 3:57:27 AM12/6/17
to
"fir" schreef in bericht
news:1c76277b-d795-4fa1...@googlegroups.com...
>
>his is offtopic but maybe someone here will/would know
>
>i dont like to read a weeks on tcp and sockets as this is a lot and
>confusing
>(i prefer this time to spend on c/graphics etc)
>
>i got some old tcp-server (on winapi winsock2) code, that worked but it was
>not tested/inspected for being ok and was yet only working in blocking mode
>
>the code goes
>
>int SetupBlockingWinsockServer()
>{
>
> WSADATA wsaData;
> WSAStartup(MAKEWORD(2,2), &wsaData);
>
> /// Creating socket
>
> servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
>
> SOCKADDR_IN sin;
> sin.sin_family = PF_INET;
> ...

When developing new software, don't use such old (IPv4 only) code. Invest
some time (you don't need weeks) to write future proof code.

fir

unread,
Dec 6, 2017, 12:09:37 PM12/6/17
to
im a noob in networking at all,
at start i just need anythig that will work - right now im searching btw for a code snipped for firing non-blocking connect on client side
(some 2h of slow googling and reading dont show me that snippet, does anybody maybe have that? tnx)

Fred.Zwarts

unread,
Dec 7, 2017, 2:49:58 AM12/7/17
to
"fir" schreef in bericht
news:cd8a5b40-e4ed-4f13...@googlegroups.com...
Why do you need non-blocking connect? It usually causes code that is
difficult to read, because it is not sequential. C++ makes it easy to create
a separate thread to make the connection, so that other threads can continue
to do their work. It is no problem if a separate thread blocks.

fir

unread,
Dec 7, 2017, 5:01:12 AM12/7/17
to
i managed to made nonblocking sends and receives also nonblocking accept connection on serber side -
it was all fairly easy, you just
repeat those calls and they return
zero (metafiorically speaking) when nothing comes and return something wen comes - its not harder than blocking and nonblocking imo should be standard (blocking you could maybe probably even not mention)

but is i said i still not found nonblocking connect.. it seems is somewhat more complicated becouse they failed something, read

" Due to ambiguities in version 1.1 of the Windows Sockets specification, error codes returned from connect while a connection is already pending may vary among implementations. As a result, it is not recommended that applications use multiple calls to connect to detect connection completion. "

this is page on this but still no code example

https://msdn.microsoft.com/en-us/library/windows/desktop/ms737625(v=vs.85).aspx

Chris Vine

unread,
Dec 7, 2017, 5:36:02 AM12/7/17
to
There is no point in doing nonblocking i/o unless you are using an
event loop, otherwise you are just doing a CPU-expending busy version of
normal blocking i/o.

On unix you do this by basing your event loop on the select() or poll()
POSIX system calls (linux and some BSDs have a faster version, epoll()
and BSDs also have kqueue).

I believe windows has select() support, and also has its own
windows-only event system as well (I don't program windows). Indeed,
the Microsoft documentation page to which you have referred explicitly
tells you this: "Use the select function to determine the completion of
the connection request by checking to see if the socket is writeable."

You know when an asynchronous connect has occurred because when it has,
the file descriptor will signal itself to select()/poll() as ready to
write. More completely, a non-blocking connect will return
immediately with the EINPROGRESS error set and (from the man page) you
use "select(2) or poll(2) for completion by selecting the socket for
writing. After select(2) indicates writability, use getsockopt(2) to
read the SO_ERROR option at level SOL_SOCKET to determine whether
connect() completed successfully (SO_ERROR is zero) or
unsuccessfully (SO_ERROR is one of the usual error codes listed here,
explaining the reason for the failure)".

You need to look at the documentation.

Chris

fir

unread,
Dec 7, 2017, 8:23:26 AM12/7/17
to
i want a piece of code, becouse i usually do more things than one at the same time and a long reading session will stop that all

getting just code sniped and im done with this .. weird i cant find it (not googled very long but some notable amount and didint found it yet)

fir

unread,
Dec 7, 2017, 9:50:04 AM12/7/17
to
i found something
that would be



int WaitForServerConnectionUnblocked()
{
u_long no_block=1;
ioctlsocket(clientSock,FIONBIO,&no_block);

//connect to the server
// iResult = connect(client, (sockaddr*)&server, sizeof(server));
int retVal = connect(clientSock,(LPSOCKADDR)&serverInfo, sizeof(serverInfo));

if( retVal == SOCKET_ERROR)
{
int iError = WSAGetLastError();
//check if error was WSAEWOULDBLOCK, where we'll wait
if(iError == WSAEWOULDBLOCK)
{
/// cout << "Attempting to connect.\n";

fd_set Write, Err;
TIMEVAL Timeout;

FD_ZERO(&Write);
FD_ZERO(&Err);

FD_SET(clientSock, &Write);
FD_SET(clientSock, &Err);
Timeout.tv_sec = 0;
Timeout.tv_usec = 30*1000;

int iResult = select(0, NULL, &Write, &Err, &Timeout);

if(iResult == 0)
{
// cout << "Connect Timeout (" << TimeoutSec << " Sec).\n";
return 0;

}
else
{
if(FD_ISSET(clientSock, &Write))
{
// cout << "Connected!\n";
return 1;
}
if(FD_ISSET(clientSock, &Err))
{
// cout << "Select error.\n";
return 0;
}
}
}
else
{
// cout << "Failed to connect to server.\n";
// cout << "Error: " << WSAGetLastError() << endl;
// WSACleanup();
return 0;
}
}
else
{
//connected without waiting (will never execute)
//cout << "Connected!\n";
return 1;

}
}
/////////////////

i would yet need a bit to digest it

it looks like blocking but here you
could just set the timeout to small
value so the client will not half-hang as with blocked where it was also like nonblocking but with a timeout like 1.5 seconds, here i set 30 ms and it seem to work
(i assume here that when i returned 1 it is connected , when returned 0 it is not connected and i should repeat the attempts by calling it again)

sometiomes thoug rarely it seems not to connect when i set up both client and server and it probably would need to be inspected yet,
maybe there is yet some bug somewhere

Richard

unread,
Dec 7, 2017, 1:47:02 PM12/7/17
to
[Please do not mail me a copy of your followup]

"Fred.Zwarts" <F.Zw...@KVI.nl> spake the secret code
<p0arqh$e04$1...@gioia.aioe.org> thusly:

>Why do you need non-blocking connect? It usually causes code that is
>difficult to read, because it is not sequential. C++ makes it easy to create
>a separate thread to make the connection, so that other threads can continue
>to do their work. It is no problem if a separate thread blocks.

There are libraries now that make asynchronous code read like
sequential regular code. Facebook's Folly future is one example, but
there are others.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Chris M. Thomasson

unread,
Dec 7, 2017, 6:51:48 PM12/7/17
to

Jorgen Grahn

unread,
Jan 9, 2018, 1:39:25 AM1/9/18
to
On Thu, 2017-12-07, Chris Vine wrote:
...
> There is no point in doing nonblocking i/o unless you are using an
> event loop, otherwise you are just doing a CPU-expending busy version of
> normal blocking i/o.
>
> On unix you do this by basing your event loop on the select() or poll()
> POSIX system calls (linux and some BSDs have a faster version, epoll()
> and BSDs also have kqueue).
>
> I believe windows has select() support, and also has its own
> windows-only event system as well

I seem to remember it's limited, and only works on networking sockets.

> (I don't program windows).

Me neither, so I might be dead wrong.

There's also Boost.Asio, if you want to learn and use an abstraction
on top of the OS. Although I imagine it's hard to use correctly if
you're not already familiar with non-blocking I/O ...

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Richard

unread,
Jan 9, 2018, 1:19:00 PM1/9/18
to
[Please do not mail me a copy of your followup]

Jorgen Grahn <grahn...@snipabacken.se> spake the secret code
<slrnp58osh.e...@frailea.sa.invalid> thusly:

>On Thu, 2017-12-07, Chris Vine wrote:
>> I believe windows has select() support, and also has its own
>> windows-only event system as well
>
>I seem to remember it's limited, and only works on networking sockets.

Correct. On Windows, select() comes from WinSock and is only intended
for use with sockets.

>There's also Boost.Asio, if you want to learn and use an abstraction
>on top of the OS. Although I imagine it's hard to use correctly if
>you're not already familiar with non-blocking I/O ...

Boost.Asio properly integrates sockets and other forms of asynchronous
I/O on Windows and non-Windows platforms. If you want portable
asynchronous I/O, it seems to be the only (best?) solution around.
Since Boost.Asio is on track to be the standard library interface for
networking and asynchronous I/O, it seems worthwhile spending the time
learning how to use that API.
0 new messages