1. 程式人生 > >Linux Socket - 內核非阻塞功能

Linux Socket - 內核非阻塞功能

由於 有變 增加 連接建立 ioc eval type ddr ont

select 函數

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval*timeout); 

fd_set * readfds

需要監視變化的文件描述符
    只要有一個文件可讀就返回>0
    沒有文件可讀
        超出timeout時間,返回=0
    發生錯誤返回負值
傳入NULL表示不關心任何文件 

fd_set * readfds

需要監視變化的文件描述符
    只要有一個文件可寫就返回>0
    沒有文件可讀
        超出timeout時間,返回=0
    發生錯誤返回負值
傳入NULL表示不關心任何文件

fd_set * errorfds

同上:監視異常文件

struct timeval* timeout

select的超時時間
為NULL時:select置於阻塞狀態
    直到監視文件發生變化位置
為0s0ms時:select變為純非阻塞函數
    不管文件描述符是否變化都立刻返回
        有變化返回正數
        無變化返回0
大於0時為等待的超時時間
    select在timeout內阻塞

返回值

有可讀文件:表示可讀文件的數量 返回值>0
沒有可讀文件:判斷timeout參數超時
    超出timeout時間後 返回值=0
    

FD_ZERO

清空文件描述符集

FD_SET

在文件描述符集合中增加一個新的

FD_CLR

刪除一個文件描述符

FD_ISSET

測試指定的文件描述符是否在集合中

SOCKET函數

int socket(int domain, int type, int protocol);
int sockfd=socket(AP_INET, SOCK_STREAM | SOCK_NOBLOCK, IPPROTO_TCP);

ACCEPT函數

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
    flags:  SOCK_NOBLOCK
            SOCK_CLOEXEC

FCNTL函數

fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);

IOCTL函數

ioctl(sockfd, FIONBIO, 1);//1:非阻塞 0:阻塞

accept,connect,recv(recvfrom),send(sendto),closesocket,select(poll或epoll)

1)accept在阻塞模式下,沒有新連接時,線程會進入睡眠狀態;非阻塞模式下,沒有新連接時,立即返回WOULDBLOCK錯誤。

2)connect在阻塞模式下,僅TCP連接建立成功或出錯時才返回,分幾種具體的情況,這裏不再敘述;非阻塞模式下,該函數會立即返回INPROCESS錯誤(需用select檢測該連接是否建立成功)

3)recv/recvfrom/send/sendto很好理解,因為這兩類函數讀寫socket文件描述符的接收/發送緩沖區。

4) select/poll/epoll並不是真正意義上的阻塞,它們的阻塞是由於它們最後一個timeout參數決定的,timeout大於0時,它們會一直等待直到超時才退出(相等於阻塞了吧,^_^),而timeout=-1即永遠等待。

5)closesocket也不是真正意義上的阻塞,它其實是指是否等待關閉。它受套接字選項SO_LINGER和SO_DONTLINGER的影響。

若SO_DONTLINGER或SO_LINGER的間隔=0時,closesocket就是非等待關閉的,但是當SO_LINGER的間隔>0時,closesoket就是等待關閉的,直到剩余數據都發送完畢或直到超時才退出。

(但是這個地方只有對於阻塞的套接口才有用,如果是非阻塞的套接口,它會立即返回並且指示錯誤WOULDBLOCK)。

Linux Socket - 內核非阻塞功能