I have a Winsock based server application which uses Windows Winsock I/O Completion Ports.
As such, each connection accepted is associated with the listening socket to start receiving notifications (read, write, close etc').
The listening socket has a backlog of 100 pending connections.
All is good.
At some point I want to stop accepting new connections yet keep communication with already connected existing connected sockets.
I figured I could do one of:
Stop calling WSAAccept().
Set the backlog to zero, effectively disallowing any connection to pend.
Call shutdown() & closesocket() on the listening socket.
Now, option #1 gives the expected results; My application doesn't process new connections, BUT it does accept up to the backlog's amount (100). Connections are practically made - I don't want it!
Option #2; Can I do that? How? Couldn't find on MSDN nor google. The documentation of listen() at MSDN says;
If the listen function is called on an
already listening socket, it will
return success without changing the
value for the backlog parameter.
Setting the backlog parameter to 0 in
a subsequent call to listen on a
listening socket is not considered a
proper reset, especially if there are
connections on the socket.
Not good for me.
If I could do so in a safe way I would combine it with option #1, effectively really stopping establishing any new connections on the machine (through the listening port!).
Option #3 actually works; After closing the listening socket I can still communicate with existing connections, and the backlog is gone (well, closed the listening socket!).
My concern is that this approach might have some side-effects. Can anyone confirm?
You can simply close the listening socket. The accepted connections have their own sockets and they will not be affected by closing the listening socket.
For example, in the Microsoft documentation there is a sample server application where basic socket usage is demonstrated. There the listening socket is closed before communication over the accepted socket is done (before the do-while-loop).
Related
Dear Stackoverflowers,
I am researching networking a bit and I decided I'd like to create a small and simple networking library with Winsock. (I am using Completion Ports and Overlapped IO though)
As I researched a bit I came to the following steps for a TCP Listener(Correct me if I am wrong):
Create a Listening Socket
Bind it to a port/IP
Listen on it
When a new connection is created, give a seperate Socket for that connection.
Listener continue's to listen, the specific connection is handled as needed.
EDIT: With a 'connection' from here I mean communication between the server and distinct clients.
Though for an UDP Listener we need to make use of WSARecvFrom which returns the IP address at the lpFrom parameter. Now I was wondering the following:
Is it better to make one UDP Socket listen to incoming connections on a specific port with WSARecvFrom and create new sockets for every specific connection? Or could I just use the UDP Socket itself with WSASendTo. Would that cause any performance penalties if one UDP Socket is used for for example 1000 connections? Or would it be the same or even better then creating/duplicating seperate Sockets for each different incoming connection?
Note: If multiple sockets are needed how would you handle sockets listening on the same port or could a client accept UDP from different ports?
Hope you guys can help!
Ps. Extra tips are always welcome!
Unlike TCP, UDP is connection-less, and as such you don't need to create separate sockets for each party. One UDP socket can handle everything. Bind it to a local IP/Port and call WSARecvFrom() once, and when it reports data to your IOCP you can process the data as needed (if another thread if needed) and then call WSARecvFrom() again. Each time new data arrives, you have to look at the reported lpFrom address to know the IP/Port of the sender. And yes, you can use the same UDP socket for sending data to each sender when needed.
I need to accept multiple connections to the same port.
I'm using socket in C++, i want to do something like the SSH do.
I can do an ssh user#machine "ls -lathrR /" and run another command to the same machine, even if the first one still running.
How can i do that?
Thanks.
What you want is a multithreaded socket server.
For this, you need a main thread that opens up a socket to listen to (and waits for incoming client connections). This has to go into a while loop of some sort.
Then, when a client connects to it, the accept() function will unblock and at that point you need to serve the client request by passing on the request to a thread that will deal with it.
The server side will loop back and wait for another connection whilst the previous thread carries on its task.
You can either create threads as you need, or use a thread pool which might be more efficient (saving on time initialising new threads).
Have a look here for some more details.
Look for multithreaded server socket on the web, specifically bind(), listen() and accept() from the server side.
You need to read up on ::listen() and ::accept().
The former will set up your socket for listening. You then need a loop (probably in its own thread) which uses ::accept() which will return each time a new connection arrives.
That loop should then spawn a new thread to which you should pass the file descriptor received from ::accept() and then handles all I/O on that socket from thereon.
Old question is old, but I feel no one who answered understood the OP's question.
You're misunderstanding how ssh works. When you send multiple commands/multiple connections to a server over ssh, there is actually only ONE program on the server you're connecting to that is receiving all those commands.
Sshd (the ssh daemon) runs on the server, and is a multithreaded socket server (see fduff's answer). This is the only program that listens on port 22, and handles all incoming ssh connections by itself.
My application connects as a client across an ethernet to a server process.
As the server is well known and will not change, UDP and TCP are both setup using
socket();
setsockopt(SO_REUSEADDR);
bind();
connect();
The connection protocol includes heartbeats sent both ways.
When I detect an error with the connection e.g. hearbeat timeout, I need to reset the connection.
Is it sufficient just to connect() to the NULL address and then re-connect() after a short pause, or should I close the socket and then reinitialise from scratch?
thanks
After a socket error you have to discard the one in hand and restart the setup with a new socket.
Winsock documentation, for example:
When a connection between sockets is
broken, the sockets should be
discarded and recreated. When a
problem develops on a connected
socket, the application must discard
and recreate the needed sockets in
order to return to a stable point.
You have to close(2) the socket and re-do everything again. Why do you bind(2) on the client?
I want to allow only one connection at a time from my TCP server. Can you please tell, how to use listen without backlog length of zero.
I m using the code(given below), but when i launch 2 client one by one, both gets connected. I m using VC++ with winsock2.
listen(m_socket,-1);
passing zero as backlog is also not working.
Waiting for ur reply.
Regards,
immi
If you can indeed limit your application to only use Winsock 2, you can use its conditional accept mechanism:
SOCKET sd = socket(...);
listen(sd, ...);
DWORD nTrue = 1;
setsockopt(sd, SOL_SOCKET, SO_CONDITIONAL_ACCEPT, (char*)&nTrue, sizeof(nTrue));
This changes the stack's behavior to not automatically send SYN-ACK replies to incoming SYN packets as long as connection backlog space is available. Instead, your program gets the signal that it should accept the connection as normal -- select(), WSAEventSelect(), WSAAsyncSelect()... -- then you call WSAAccept() instead of accept():
sockaddr_in sin;
WSAAccept(sd, (sockaddr*)&sin, sizeof(sin), ConditionalAcceptChecker, 0);
You write the function ConditionalAcceptChecker() to look at the incoming connection info and decide whether to accept the connection. In your case, you can just return CF_REJECT as long as you're already processing a connection.
Again, beware that this mechanism is specific to Winsock 2. If you need portable behavior, the other posts' advice to close the listening socket while your program already has a connection is better.
You may set backlog equal to 1, since this is number of connections you want.
But AFAIK there's no hard warranty on queue size (this doc says it would be 1.5 * backlog on BSD, e.g.).
IMHO, you'd better control number of connections manually by not accept()'ing connections after some limit.
I would say, only accept once. If you only want one client at a time on your server you can use also only one thread to perform the handling. The backlog limits only the amount of pending connections handled by the system for accepting (the queue is empty again after the first accept so the next client gets into the backlog) not the amount of connections!
That's not what the listen backlog is for.
The listen backlog affects a queue that's used for pending connections, it allows the TCP stack to queue up pending connections for you to accept.
To do what you want to do you need to accept the one connection that you're allowing and then close the listening socket. Once you've finished with your single client you can recreate your listening socket and listen for a new connection. This will prevent more than a single client connecting to you but there will be no way for the client to know that you're actually running and accepting connections on a "one at a time" basis. All clients except the one that manages to connect will think you're just not there.
It's probably a better design to keep your listening socket open and accept all connections but once you have you "one" active connection you simply accept and then either send an application level message to your client telling it that you cant accept any more connections OR if you can't do that, simply close the new connection.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm writing a client-server pair in C++ using Linux sockets. I want the server to listen for a connection, and while one client is connected the server should reject any other clients that try to connect.
I tried implementing this by setting the backlog parameter in the listen function to 0 and to 1 and neither one of those values seems to work. The first client connects as expected, but any subsequent clients just block while the first client finishes. What's really confusing to me is that they don't block on connecting to the server, they block on the first read.
I used the code here to get started writing my client and server. Does anyone know what I need to change to get the server to accept only one client connection, and drop any subsequent connection attempts?
When you accept a connection, a new socket gets created. The old one is still used to listen for future connections.
Since you want to only allow 1 connection at a time, you could just accept the connections, and then close the new accepted socket if you detect you are already processing another.
Is there a net difference that you are looking for compared to closing the new accepted socket right after the accept? The client will know as soon as it tries to use its socket (or right away if it is already waiting on the server with a read call) with a last error of: server actively closed the connection.
Just don't fork() after accept().
This pseudo-C-code will only accept one client at once.
while(1) {
listen()
accept()
*do something with the connection*
close()
}
You could close your original socket that's listening for connections after accepting the first connection. I don't know if the socket class you're using will allow you to do that though.
Sounds like you need to implement it manually. Let a client connect, then send a disconnect message from the server to the client if there's already another client connected. If the client receives this message let it disconnect itself.
Since you want to only allow 1 connection at a time, you could just accept the connections, and then close the new accepted socket if you detect you are already processing another.
I think it should be the listen socket that to be closed.
When the first connection is established, you close the original listen socket.
And after that no more connections can be established.
After the first connection ends, you can create a new socket to listen again.
If you have control over the clients, you can make the sockets non-blocking. In this case they'll return the error message EINPROGRESS.
I'm still looking for how to change the socket to be non-blocking. If anybody know how to offhand, feel free to edit the answer.
let the listening socket die after accepting and starting a new connection. Then when that connection is done, have it spin off a new listening socket.
You might have the socket option TCP_DEFER_ACCEPT set on your listening socket:
TCP_DEFER_ACCEPT (since Linux 2.4)
Allows a listener to be awakened only when data arrives on the socket.
Takes an integer value (seconds), this can bound the maximum number of
attempts TCP will make to complete the connection. This option should
not be used in code intended to be portable.
I would assume it would lead to the effect you described, that the connecting client doesn't block on the connect, but on the subsequent read. I'm not exactly sure what's the options default setting and to what it should be set to disable this behavior, but probably a value of zero is worth a try:
int opt = 0;
setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, &opt, sizeof(opt));
As far as I see, it is not possible to listen for exactly one connection.
Tcp involves a 3-way handshake. After the first syn packet is received the kernel puts that "connection" in a wait queue, answers with an syn/ack and waits for the final ack. After this is received it moves the connection from the wait queue to the accept queue, where it can be picked up by the application using the accept() call. (For details have a look here.)
On linux the backlog argument only limits the size of the accept queue. but the kernel will still do the 3-way handshake magic. The client receives syn/ack and answers with the final ack and calls the connection established.
Your only options are, either shutting down the listening socket as soon as you accepted the first connection. (This might however result in other connection already being available.) Or you actively accept other connections and close them immediately to notify the client.
The last option you have is the one you are already using: let the server queue your connections and process them one after the other. Your clients will block in that case.