Advertisement

Problem with listening TCP/IP sockets under linux

Started by February 23, 2004 08:59 PM
4 comments, last by Evil Steve 20 years, 11 months ago
I've been messing about with my socket class, and i realised something. If I bind and listen on a port (23 in this case), then close the socket, and try to rebind and relisten, it doesn't work - i get error code #98 from bind(), which isn't listed as a valid return error code for bind(). I close the socket properly, as far as i'm aware:

void CBaseSocket::Disconnect()
{
   if(m_sock != INVALID_SOCKET)
   {
#ifdef WIN32
      shutdown(m_sock,SD_SEND);
#else
      shutdown(m_sock,SHUT_WR);
#endif
      closesocket(m_sock);
      m_sock = INVALID_SOCKET;
   }
}
I only get this problem under linux, it workd fine under windows (2000). I'm running Red Hat 9. It doesn't seem to matter how long i wait before i rebind, i have to exit the application and wait for a while (about 2 - 5 mins), then it works fine - I assume the OS is doing random housekeeping and it cleans up my socket for me. Heres the code i use to listen:

bool CBaseSocket::Listen(int nPort)
{
sockaddr_in sockAddr;
   
   // Create Socket //

   m_sock = socket(PF_INET,SOCK_STREAM,0);
   if(m_sock == INVALID_SOCKET)
   {
      m_strError = "Fatal Error: socket() Failed! " + WSAErrorAsString(Error);
      return false;
   }
   
   // Setup Address //

   memset(&sockAddr,0,sizeof(sockAddr));
   sockAddr.sin_family = AF_INET;
   sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
   sockAddr.sin_port = htons(nPort);
   
   // Bind socket to To Address //

   if(bind(m_sock,(sockaddr*)&sockAddr,sizeof(sockaddr_in)) == SOCKET_ERROR)
   {
      m_strError = "Fatal Error: bind() Failed! " + WSAErrorAsString(Error);
      closesocket(m_sock);
      m_sock = INVALID_SOCKET;
      return false;
   }
   
   // Listen on Socket //

   if(listen(m_sock,5) == SOCKET_ERROR)
   {
      m_strError = "Fatal Error: listen() Failed! " + WSAErrorAsString(Error);
      closesocket(m_sock);
      m_sock = INVALID_SOCKET;
      return false;
   }
   
   return true;
}
Anyone had this problem? Is there something i'm missing that windows is more tolerant about (e.g. unbind()?) I checked the HawkNL source, and it listens and closes sockets the same way as me. Cheers, Steve [edited by - Evil Steve on February 23, 2004 10:01:51 PM]
If i look at netstat just after closing the application, I get this:
[root@server MUD]# netstatActive Internet connections (w/o servers)Proto Recv-Q Send-Q Local Address           Foreign Address         Statetcp        0      0 server:netbios-ssn      Steve:1027              ESTABLISHEDtcp        1      0 server:telnet           Steve:2079              CLOSE_WAIT

Which shows that theres a connection to port 23 (where i bound to) from my machine (because i was connected to it), thats closing...
Advertisement
First of all, to eliminate your problem with waiting to use the socket again, add this code after you create the socket:

unsigned long arg = 1; // set to zero to disable reusing
setsockopt(m_Handle, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, sizeof(unsigned long));

If you dont set the socket to be reused, you will have to wait until the OS stops using the socket. Obviously this will be different for every OS.

Intro Engine
Ahh! Great, thanks
The reason the address can''t immediately be re-used is because some outstanding TCP packets may still be on the network somewhere, and get to your machine later. For full correctness, the kernel needs to prevent such late packets from showing up after you''ve closed the socket and then re-opened it.

Typically, a socket will be in CLOSE_WAIT for about two minutes before you can re-bind the socket. Setting REUSEADDR when you open it the first time is usually mostly harmless, though, as a TCP packet arriving even 10 seconds late is pretty unlikely, and pretty unlikely to cause an actual problem if it does.

Note that for UDP, this problem doesn''t exist, for obvious reasons.
enum Bool { True, False, FileNotFound };
Ah, i see. Well, setting REUSEADDR fixed the problem completely.

Thanks all

This topic is closed to new replies.

Advertisement