今天寫一個簡單的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參數。