Reputation: 633
I have a program which works as a simple tcp server, it will accept and serve as much as 4 clients. I wrote the following code snippet to archive this goal, for more clearly, I replace some MACRO with "magic number".
while(1) {
int ret = 0;
///
// sock_ is the listening socket, rset_conn_ only contains sock_
//
if(select(sock_ + 1, &rset_conn_, NULL, NULL, &timeo_) <= 0) {
ret = 0;
}
if(FD_ISSET(sock_, &rset_conn_)) {
ret = 1;
}
///
// because the rule select() clears file descriptor and updates timeout is
// complex, for simplicity, let's reset the sock_ and timeout
//
FD_SET(sock_, &rset_conn_);
timeo_.tv_sec = 0;
timeo_.tv_usec = 500000;
if(! ret) {
continue ;
}
///
// csocks_ is an 4 integer array, used for storing clients' socket
//
for(int i = 0 ; i < 4 ; ++i) {
if((-1 == csocks_[i]) && (-1 != (csocks_[i] = accept(sock_, NULL, NULL)))) {
break ;
}
}
}
now, when less than 4 clients connect, this code snippet works normally, but when the 5th client connects, as you can see, it will not be accepted in the for loop, this results in such a problem: in the following loops of while, select() call keeps returning with sock_ bit in rset_conn_ set --- just because I don't accept it!!
I realize that I should not just ignoring it(not accept) in the for loop, but how can I handle it properly by telling kernel "I don't want to accept this client, so not tell me this client want to connect me any more!"?
Any help will be appreciated..
Update:
I can not stop calling select() call, because the clients already connected may disconnect, and then my program will have room for new clients. I need to keep listening on a socket to accept connection, not stop listening when reaches one point.
Upvotes: 1
Views: 2759
Reputation: 311054
You can remove the listening socket from the readFDs while there are four existing clients, and put it back when one drops off, but I don't see the point. Why only four clients? Why not remove the limit and eliminate the whole problem? Real servers are not built this way.
Upvotes: 2
Reputation: 598384
There is no socket API to tell the kernel to ignore pending connections (well, on Windows, there is a callback in WSAAccept()
for that, but that is a Microsoft-specific extension).
On most platforms, you have to either:
close()
the listening socket when your array fills up, then reopen it when a client disconnects.
accept()
the client but immediately close()
it if the array is full.
stop calling select()
and accept()
while your array is full. Any clients that are in the backlog will time out eventually, unless your array fills up and you accept()
a pending client before it times out.
Upvotes: 3
Reputation: 182883
Why are you asking a question you don't want the answer to? Stop calling select
on the listening socket if you don't want to be told that there's an unaccepted connection.
I can not stop calling select() call, because the clients already connected may disconnect, and then my program will have room for new clients. I need to keep listening on a socket to accept connection, not stop listening when reaches one point.
You can stop calling select now. When a client disconnects, then start calling select
again. Only ask questions you want the answers to.
Upvotes: 5