linux 網路程式設計 四 非阻塞通訊poll

2021-06-12 17:43:42 字數 4225 閱讀 6781

#include

int poll(struct pollfd fds, nfds_t nfds, int timeout);

typedef struct pollfd pollfd_t;

typedef unsigned long   nfds_t;

fds:是乙個struct pollfd結構型別的陣列,用於存放需要檢測其狀態的socket描述符;每當呼叫這個函式之後,系統不會清空這個陣列,操作起來比較方便;特別是對於socket連線比較多的情況下,在一定程度上可以提高處理的效率;這一點與select()函式不同,呼叫select()函式之後,select()函式會清空它所檢測的socket描述符集合,導致每次呼叫select()之前都必須把socket描述符重新加入到待檢測的集合中;因此,select()函式適合於只檢測乙個socket描述符的情況,而poll()函式適合於大量socket描述符的情況;

nfds:nfds_t型別的引數,用於標記陣列fds中的結構體元素的總數量;

timeout:是poll函式呼叫阻塞的時間,單位:毫秒;

>0:陣列fds中準備好讀、寫或出錯狀態的那些socket描述符的總數量;

==0:陣列fds中沒有任何socket描述符準備好讀、寫,或出錯;此時poll超時,超時時間是timeout毫秒;換句話說,如果所檢測的socket描述符上沒有任何事件發生的話,那麼poll()函式會阻塞timeout所指定的毫秒時間長度之後返回,如果timeout==0,那麼poll() 函式立即返回而不阻塞,如果timeout==inftim,那麼poll() 函式會一直阻塞下去,直到所檢測的socket描述符上的感興趣的事件發生是才返回,如果感興趣的事件永遠不發生,那麼poll()就會永遠阻塞下去;

-1:  poll函式呼叫失敗,同時會自動設定全域性變數errno;

如果待檢測的socket描述符為負值,則對這個描述符的檢測就會被忽略,也就是不會對成員變數events進行檢測,在events上註冊的事件也會被忽略,poll()函式返回的時候,會把成員變數revents設定為0,表示沒有事件發生;

另外,poll() 函式不會受到socket描述符上的o_ndelay標記和o_nonblock標記的影響和制約,也就是說,不管socket是阻塞的還是非阻塞的,poll()函式都不會收到影響;而select()函式則不同,select()函式會受到o_ndelay標記和o_nonblock標記的影響,如果socket是阻塞的socket,則呼叫select()跟不呼叫select()時的效果是一樣的,socket仍然是阻塞式tcp通訊,相反,如果socket是非阻塞的socket,那麼呼叫select()時就可以實現非阻塞式tcp通訊;

所以poll() 函式的功能和返回值的含義與 select() 函式的功能和返回值的含義是完全一樣的,兩者之間的差別就是內部實現方式不一樣,select()函式基本上可以在所有支援檔案描述符操作的系統平台上執行(如:linux 、unix 、windows、macos等),可移植性好,而poll()函式則只有個別的的作業系統提供支援(如:sunos、solaris、aix、hp提供支援,但是linux不提供支援),可移植性差;

#include  #include  /* basic system data types */

#include /* basic socket definitions */

#include /* sockaddr_in{} and other internet defns */

#include /* inet(3) functions */

#include #include #include #include #include /* poll function */

#include #define maxline 10240

#ifndef open_max

#define open_max 40960

#endif

void handle(struct pollfd* clients, int maxclient, int readyclient);

int main(int argc, char **argv)

int opt = 1;

if (setsockopt(listenfd, sol_socket, so_reuseaddr, &opt, sizeof(opt)) < 0)

if(bind(listenfd, (struct sockaddr *) &servaddr, socklen) == -1)

if (listen(listenfd, listenq) < 0)

clients[0].fd = listenfd;

clients[0].events = pollin;

int i;

for (i = 1; i< open_max; i++)

clients[i].fd = -1;

maxi = listenfd + 1;

printf("pollechoserver startup, listen on port:%d\n", servport);

printf("max connection is %d\n", open_max);

for ( ; ; )

if (clients[0].revents & pollin)

}if (i == open_max)

if (i > maxi)

maxi = i;

--nready;

}handle(clients, maxi, nready);

}}void handle(struct pollfd* clients, int maxclient, int nready)

if (nread == 0)

write(connfd, buf, nread);//響應客戶端

if (--nready <= 0)//沒有連線需要處理,退出迴圈

break;}}

}

#include  #include  /* basic system data types */

#include /* basic socket definitions */

#include /* sockaddr_in{} and other internet defns */

#include /* inet(3) functions */

#include /*gethostbyname function */

#include #include #include #include #define maxline 1024

void handle(int connfd);

int main(int argc, char **argv)

if (argc == 3)

if (argc > 3)

connfd = socket(af_inet, sock_stream, 0);

bzero(&servaddr, sizeof(servaddr));

servaddr.sin_family = af_inet;

servaddr.sin_port = htons(servport);

inet_pton(af_inet, servinetaddr, &servaddr.sin_addr);

if (connect(connfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)

printf("welcome to echoclient\n");

handle(connfd); /* do it all */

close(connfd);

printf("exit\n");

exit(0);

}void handle(int sockfd)

/*//也可以不用標準庫的緩衝流,直接使用系統函式無快取操作

if (read(stdin_fileno, sendline, maxline) == 0)

*/n = write(sockfd, sendline, strlen(sendline));

n = read(sockfd, recvline, maxline);

if (n == 0)

write(stdout_fileno, recvline, n);

//如果用標準庫的快取流輸出有時會出現問題

//fputs(recvline, stdout);

}}

linux 網路程式設計 三 非阻塞通訊select

int select int nfds,fd set readfds,fd set writefds,fd set exceptfds,struct timeval timeout 說明 int maxfdp是乙個整數值,是指集合中所有檔案描述符的範圍,即所有檔案描述符的最大值加1。fd set r...

linux 網路程式設計 三 非阻塞通訊select

int select int nfds,fd set readfds,fd set writefds,fd set exceptfds,struct timeval timeout 說明 int maxfdp是乙個整數值,是指集合中所有檔案描述符的範圍,即所有檔案描述符的最大值加1。fd set r...

linux網路程式設計中阻塞和非阻塞socket的區別

阻塞socket和非阻塞socket 讀操作 對於阻塞的socket,當socket的接收緩衝區中沒有資料時,read呼叫會一直阻塞住,直到有資料到來才返 回。當socket緩衝區中的資料量小於期望讀取的資料量時,返回實際讀取的位元組數。當sockt的接收緩衝 區中的資料大於期望讀取的位元組數時,讀...