Hi all,

I am constructing a program on TCP sockets. The server should be able to accept connections from more than 1 clients. My programs seem working fine when accepting connections. Now the problem is: when I try to terminate one of the client programs,
the server program would also terminate due to error in accept() (of course other client programs would terminate as well because the server shuts down). How can I keep the server running for listening and accepting new connections?

Any help would be appreciated! Thanks in advance :)

/******************** Threading ********************/
DWORD WINAPI receive_cmds(LPVOID lpParam) {
  SOCKET current_client = (SOCKET)lpParam;

/* Do some server stuffs here*/

  closesocket(current_client);
  WSACleanup();
  ExitThread(0);
}

/******************** Main program ********************/
int main() {
  SOCKET server_sockfd, client_sockfd;
  int client_len, server_len;
  int optsize = sizeof(BOOL);
  char optval = '1';
  struct sockaddr_in server_address, client_address;
  DWORD thread;

  WSADATA wsadata;
  if(WSAStartup(0x101,(LPWSADATA)&wsadata) != 0) {
    WSACleanup();
    exit(1);
  }

RESETPORT:
  server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
  setsockopt(server_sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optsize);
  setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, optsize);
  if(server_sockfd == SOCKET_ERROR) {
    WSACleanup();
    exit(1);
  }

  server_address.sin_family = AF_INET;
  server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
  server_address.sin_port = 5200;
  server_len = sizeof(server_address);

  if(bind(server_sockfd, (struct sockaddr *)&server_address, server_len) < 0) {
    WSACleanup();
    exit(1);
  }

  if(listen(server_sockfd, 2) < 0) {
    WSACleanup();
    exit(1);
  }

  client_len = sizeof(client_address);

  while(1) {
    client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
    if(client_sockfd == SOCKET_ERROR) {
      WSACleanup();
      goto RESETPORT;
    }
    CreateThread(NULL, 0, receive_cmds,(LPVOID)client_sockfd, 0, &thread);
  }

  closesocket(server_sockfd);
  WSACleanup();
  return 0;
}

I may be wrong but as far as I see you are using a single port to receive client requests from , but later when you intend to handle different clients in different threads you have to bind them to a different port for the connection to remain intact and communication to take place. If all threads are linked to the same port and you close that port all the connections are bound to get disconnected.
As its been some time that I have programmed in this field I may have gone wrong somewhere. Do correct me in case I am wrong.

Thanks for your help!

When I look at different examples on multiple-client socket programming, basically all of them uses the same port for listening and accepting connections from different clients, so I cannot judge whether this is the source of the problem or not.
Also, if the server have to use different ports for different clients, how can the client know which port on the server should it connect to? Since I have to assume that no. of clients is unknown, I guess I should not pre-assign the ports...

Naturally, you can have multiple connections to one port. Just think of an HTTP web server serving web pages to thousands of users connected on port 80.
The way you distinguish between clients is by socket number.

Now, you falsely assume that every time accept (or any WinSock functions) returns error, it is a fatal error.
Take a look at the documentation:
http://msdn.microsoft.com/en-us/library/ms737526(v=vs.85).aspx

You should be checking for 'INVALID_SOCKET', and then calling WsaGetLastError to get a more detailed error code. Some of these error codes are not fatal, like EWSAWOULDBLOCK.

Next, you should not blindly call accept. There are nice ways to determine whether there is a new connection pending or new data in the buffer, ready to be received. Look at functions like 'select'. I know that on Linux there are better alternatives than select, I forgot if this is the case on Windows. In any case, select will do fine for a first try.

Thanks for your help!

For the second problem you have mentioned, can it be solved if I direct the program routine to listen()?

listen (basically) just tells the OS that you will be listening for new connections on this socket. It should only be called once, for each socket you want to listen on.

select-like functions tell you when there are new connections on a socket that you are listening on. You can have select behave differently by setting socket options like blocking or non-blocking. These things are documented extensively so just google a bit for when select is used, and how you can use it in your program.

Thanks for your information. I think I will try on select() for the meanwhile.

BTW, can I use select() and threads together?

Thanks all for your help! The problem is now solved. So relieved :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.