vc++使用Create出现WSAEADDRINUSE错误的解决办法

   程序原码:

DWORD WINAPI CServerSocket:: ListenThread(LPVOID lparam)
{
 try
 {
  //加以下语句可消除Debug时出现的afxwin1.inl的报错
  //该错误在Release时是不出现的
  //AFX_MANAGE_STATE(AfxGetStaticModuleState());

  CServerSocket *pServerSocket=(CServerSocket *)lparam;  
  
  int createSucceed=pServerSocket->Create(pServerSocket->intPort);   //第2次执行时在这里出现WSAEADDRINUSE错误,原因是端口被占用
  
  if(createSucceed==0)
  {
   AfxMessageBox("_ListenTcpThread Create错误!"+pServerSocket->GetError(GetLastError()));
   return -1;
  }
  
  int listenSucceed=pServerSocket->Listen(10); //开始监听

  if(listenSucceed==0)
  {
   AfxMessageBox("_ListenTcpThread Listen错误!"+pServerSocket->GetError(GetLastError()));
   return -1;
  }
  
  CSocket recSo;
  SOCKADDR_IN client;
  int iAddrSize=sizeof(client);
    
  int intSucceed=pServerSocket->Accept(recSo,(SOCKADDR *)&client,&iAddrSize); //接受连接并取得对方IP
  ....

}

 

        先是查了不少文章,一堆搞不明白状况的家伙胡乱指点,有的说是要AfxSocketInit(),有的说换个端口就可以了!

问题是我的这个端口是监听的,我随机换的话,远程的Client哪里知道该找哪个来连接???

         总算找到下面的一段文字,把原理给说清楚了!解决办法也很清楚 !

 

        我的处理是,退出线程之前做一下SetSockOpt,代码如下:

       //停止服务程序监听
BOOL CServerSocket::StopServer()
{
       DWORD exitcode;
 
       WaitForSingleObject(m_hServerThread,500);
 
       //解决WSAEADDRINUSE错误的解决办法 start
       //加这几句可以解决:停止监听,再重新开启监听出现Create语句发生WSAEADDRINUSE错误的问题
       //问题提示端口已经被占用
       BOOL bDontLinger=FALSE; 
       this->SetSockOpt(SO_DONTLINGER,(const char *)&bDontLinger,sizeof(bDontLinger),SOL_SOCKET);
       this->Close();
       //解决WSAEADDRINUSE错误的解决办法 end

       if(!GetExitCodeThread(m_hServerThread,&exitcode))
       {
            TerminateThread(m_hServerThread,exitcode);
       }
  
       m_hServerThread=NULL;
   
       return 0;
}

   

      为什么TCP关闭后端口会处于TIME_WAIT状态?
      一般来说,tcp正常关闭需要四个包。比如a和b关闭连接,a先给b发一个fin,b会进行确认ack,然后b也会发出fin,当a接受到这个fin,并发出最后一个ack后,就会处于time_wait状态。这个时间长短跟操作系统有关,一般会在1-4分钟,也就是两倍的数据包(2msl)最大生存时间。TCP主动关闭方采用TIME_WAIT主要是为了实现终止TCP全双工连接的可靠性及允许老的重复分节在网络中消逝,等过了2msl(大约1~4分钟)后TIME_WAIT就会消失。

      所以说,主动发起关闭连接的一方会进入time_wait状态,这个时候,进程所占用的端口号不能被释放。除非在你的程序中用setsockopt设置端口可重用(SOCK_REUSE)的选项,但这不是所有操作系统都支持的,解决TIME_WAIT的办法我个人认为以下两种比较好:

1、禁用LINGER
//Socket API
BOOL bDontLinger=FALSE;  
setsockopt(m_socket,SOL_SOCKET,SO_DONTLINGER,(LPCTSTR)&bDontLinger,sizeof(BOOL));
closesocket(s);

//MFC CAsyncSocket或者CSocket
BOOL bDontLinger=FALSE; 
m_socket->SetSockOpt(SO_DONTLINGER,(const char *)&bDontLinger,sizeof(bDontLinger),SOL_SOCKET);
m_socket->Close();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值