精品理论电影在线_日韩视频一区二区_一本色道精品久久一区二区三区_香蕉综合视频

使用Create出現(xiàn)WSAEADDRINUSE錯誤的解決辦法

發(fā)布時間:2011-08-29 共1頁

  程序源碼:
  DWORD WINAPI CServerSocket:: ListenThread(LPVOID lparam)
  {
  try
  {
  //加以下語句可消除Debug時出現(xiàn)的afxwin1.inl的報錯
  //該錯誤在Release時是不出現(xiàn)的
  //AFX_MANAGE_STATE(AfxGetStaticModuleState());
  CServerSocket *pServerSocket=(CServerSocket *)lparam;
  int createSucceed=pServerSocket->Create(pServerSocket->intPort); //第2次執(zhí)行時在這里出現(xiàn)WSAEADDRINUSE錯誤,原因是端口被占用
  if(createSucceed==0)
  {
  AfxMessageBox("_ListenTcpThread Create錯誤!"+pServerSocket->GetError(GetLastError()));
  return -1;
  }
  int listenSucceed=pServerSocket->Listen(10); //開始監(jiān)聽
  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(),有的說換個端口就可以了!
  問題是我的這個端口是監(jiān)聽的,我隨機換的話,遠程的Client哪里知道該找哪個來連接???
  總算找到下面的一段文字,把原理給說清楚了!解決辦法也很清楚 !
  我的處理是,退出線程之前做一下SetSockOpt,代碼如下:
  //停止服務程序監(jiān)聽
  BOOL CServerSocket::StopServer()
  {
  DWORD exitcode;
  WaitForSingleObject(m_hServerThread,500);
  //解決WSAEADDRINUSE錯誤的解決辦法 start
  //加這幾句可以解決:停止監(jiān)聽,再重新開啟監(jiān)聽出現(xiàn)Create語句發(fā)生WSAEADDRINUSE錯誤的問題
  //問題提示端口已經(jīng)被占用
  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關(guān)閉后端口會處于TIME_WAIT狀態(tài)?
  一般來說,tcp正常關(guān)閉需要四個包。比如a和b關(guān)閉連接,a先給b發(fā)一個fin,b會進行確認ack,然后b也會發(fā)出fin,當a接受到這個fin,并發(fā)出最后一個ack后,就會處于time_wait狀態(tài)。這個時間長短跟操作系統(tǒng)有關(guān),一般會在1-4分鐘,也就是兩倍的數(shù)據(jù)包(2msl)最大生存時間。TCP主動關(guān)閉方采用TIME_WAIT主要是為了實現(xiàn)終止TCP全雙工連接的可靠性及允許老的重復分節(jié)在網(wǎng)絡中消逝,等過了2msl(大約1~4分鐘)后TIME_WAIT就會消失。
  所以說,主動發(fā)起關(guān)閉連接的一方會進入time_wait狀態(tài),這個時候,進程所占用的端口號不能被釋放。除非在你的程序中用setsockopt設(shè)置端口可重用(SOCK_REUSE)的選項,但這不是所有操作系統(tǒng)都支持的,解決TIME_WAIT的辦法我個人認為以下兩種比較好:
  禁用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();

百分百考試網(wǎng) 考試寶典

立即免費試用