問題解決:
在把win下的遊戲伺服器遷移到linux下時遇到很多問題,其中一個就是select總是返回1,經過不斷調試分析,發現原來是連接埠佔用。
在linux中的socket程式關閉時,底層TCP串連並不會立即關閉,在偵錯工具時往往會帶來問題,可以使用命令:
netstat –apn | grep <連接埠號碼>
查看你所使用的連接埠當然是不是被使用中
如果TCP的狀態是TIME_WAIT,並且你的程式關閉了,稍等一會應該TCP就會自動釋放連接埠了
而如果查看到的資訊最後有你的程式名及pid時你就得手動關閉這個程式了:
kill <pid>
或:
pkill <程式名> (要確保沒有重名的程式)
關於select的用法:
表標頭檔
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
定義函數
int select(int n,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * timeout);
函數說明
select()用來等待檔案描述詞狀態的改變。參數n代表最大的檔案描述詞加1,參數readfds、writefds 和exceptfds 稱為描述片語,是用來回傳該描述詞的讀,寫或例外的狀況。底下的宏提供了處理這三種描述片語的方式:
FD_CLR(inr fd,fd_set* set);用來清除描述片語set中相關fd 的位
FD_ISSET(int fd,fd_set *set);用來測試描述片語set中相關fd 的位是否為真
FD_SET(int fd,fd_set*set);用來設定描述片語set中相關fd的位
FD_ZERO(fd_set *set); 用來清除描述片語set的全部位
參數 timeout為結構timeval,用來設定select()的等待時間,其結構定義如下
struct timeval
{
time_t tv_sec;
time_t tv_usec;
};
如果參數timeout設為NULL則表示select沒有timeout (即一直等待直到有狀態發生改變)。
傳回值
執行成功則返迴文件描述詞狀態已改變的個數;
如果逾時返回0,代表在描述詞狀態改變前已超過timeout時間;
當有錯誤發生時則返回-1:
錯誤原因存於errno,此時參數readfds,writefds,exceptfds和timeout的值變成不可預測。errno值:
EBADF 檔案描述詞為無效的或該檔案已關閉
EINTR 此調用被訊號所中斷
EINVAL 參數n 為負值。
ENOMEM 核心記憶體不足
範例
常見的程式片段:
fs_set readset;FD_ZERO(&readset);FD_SET(fd,&readset);select(fd+1,&readset,NULL,NULL,NULL);if(FD_ISSET(fd,readset){……}