linux 網絡編程 socket bind failed 問題解決


今天寫一個簡單的socket網絡通訊的程序的時候,用ctrl+c結束server端程序之后。再次啟動server出現了bind failed:the address already in use的錯誤。在網上查了一下以后找到了原因。在此記錄一下。這個IBM的官網上說到了這一點:http://www.ibm.com/developerworks/cn/linux/l-sockpit/

具體介紹例如以下:

bind 普遍遭遇的問題是試圖綁定一個已經在使用的port。該陷阱是或許沒有活動的套接字存在,但仍然禁止綁定port(bind 返回EADDRINUSE)。它由 TCP 套接字狀態 TIME_WAIT 引起。

該狀態在套接字關閉后約保留 2 到 4 分鍾。

在 TIME_WAIT 狀態退出之后,套接字被刪除,該地址才干被又一次綁定而不出問題。

等待 TIME_WAIT 結束可能是令人惱火的一件事。特別是假設您正在開發一個套接字server。就須要停止server來做一些修改,然后重新啟動。幸運的是,有方法能夠避開 TIME_WAIT 狀態。能夠給套接字應用 SO_REUSEADDR 套接字選項,以便port能夠立即重用。

考慮清單 3 的樣例。

在綁定地址之前。我以 SO_REUSEADDR 選項調用 setsockopt

為了同意地址重用,我設置整型參數(on)為 1 (不然,能夠設為 0 來禁止地址重用)。

清單 3.使用 SO_REUSEADDR 套接字選項避免地址使用錯誤
int sock, ret, on;
struct sockaddr_in servaddr;
/* Create a new stream (TCP) socket */
sock = socket( AF_INET, SOCK_STREAM, 0 ):
/* Enable address reuse */
on = 1;
ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
/* Allow connections to port 8080 from any available interface */
memset( &servaddr, 0, sizeof(servaddr) );
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
servaddr.sin_port = htons( 45000 );
/* Bind to the address (interface/port) */
ret = bind( sock, (struct sockaddr *)&servaddr, sizeof(servaddr) );

在應用了 SO_REUSEADDR 選項之后,bind API 函數將同意地址的馬上重用。

我依照上面的指示增加這段代碼以后又出現了一個錯誤:setsockopt failed: Socket operation on non-socket。

然后又在網上查,Socket operation on non-socket 錯誤出現有兩種情況:

      1.  建立socket:

                 if(listenfd= socket(AF_INET,SOCK_STREAM, 0)==-1){

                      perror("creating socket failed!");
                      exit(-1);
                 }

           會造成在bind時出現 Socket operation on non-socket錯誤

           正確的代碼應該是:

                  if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
                        perror("creating socket failed!");
                        exit(-1);
                  }

      2.  accept時:

                 if(connfd=accept(listenfd,(struct sockaddr *)&client_addr,(socklen_t *)&sin_size)==-1){
                      perror("accept error!");
                      exit(-1);
                 }

           會造成在recv時出現  Socket operation on non-socket錯誤

           正確代碼是:

                 if((connfd=accept(listenfd,(struct sockaddr *)&client_addr,(socklen_t *)&sin_size))==-1){
                         perror("accept error!");
                         exit(-1);
                 }

   出現Socket operation on non-socket 錯誤的原因是:

            if(listenfd= socket(AF_INET,SOCK_STREAM, 0)==-1)

            if(connfd=accept(listenfd,(struct sockaddr *)&client_addr,(socklen_t *)&sin_size)==-1)

  這兩句中缺失了()造成的。

賦值符合優先級最低,導致listenfd和connfd在創建/連接成功是為0,不成功時為1

最后:

如 調用connect  socket accept  函數出錯,能夠 perror("socket"); perror("connect"); printf("%s\n",strerror(errno));都能打出詳細的錯誤。

編譯結果出現例如以下錯誤:undefined reference to 'pthread_create',應該在在編譯中要加 -lpthread參數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM