日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

select函数(一)

發布時間:2023/11/30 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 select函数(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

參數:

  • nfds:監控的文件描述符集里最大文件描述符加1,因為此參數會告訴內核檢測前多少個文件文件描述符
  • readfs:監控有讀數據到達文件描述符集合,傳入傳出參數
  • writefds:監控寫數據到達文件描述符集合,傳入傳出參數
  • exceptfds:監控異常發生到達文件描述符集合,如帶外數據到達異常,傳入傳出參數
  • timeout:定時阻塞監控時間。

?

#include <sys/select.h> void FD_CLR(int fd, fd_set *set); // 把文件描述符集里fd位清0 int FD_ISSET(int fd, fd_set *set); // 測試文件描述符集里fd是否置1 void FD_SET(int fd, fd_set *set); // 把文件描述符集合里fd位置1 void FD_ZERO(fd_set *set); // 把文件描述符集合里所有位清0

二、select函數用法圖解

三、實驗一

#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <errno.h> #include <sys/socket.h>void perr_exit(const char *s) {perror(s);exit(-1); }int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr) {int n;again:if ((n = accept(fd, sa, salenptr)) < 0) {//ECONNABORTED 發生在重傳(一定次數)失敗后,強制關閉套接字//EINTR 進程被信號中斷if ((errno == ECONNABORTED) || (errno == EINTR)){goto again; }else{perr_exit("accept error");}}return n; }int Bind(int fd, const struct sockaddr *sa, socklen_t salen) {int n;if ((n = bind(fd, sa, salen)) < 0){perr_exit("bind error");}return n; }int Connect(int fd, const struct sockaddr *sa, socklen_t salen) {int n;n = connect(fd, sa, salen);if (n < 0) {perr_exit("connect error");}return n; }int Listen(int fd, int backlog) {int n;if ((n = listen(fd, backlog)) < 0){perr_exit("listen error");}return n; }int Socket(int family, int type, int protocol) {int n;if ((n = socket(family, type, protocol)) < 0){perr_exit("socket error");}return n; }ssize_t Read(int fd, void *ptr, size_t nbytes) {ssize_t n;again:if ( (n = read(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n; }ssize_t Write(int fd, const void *ptr, size_t nbytes) {ssize_t n;again:if ((n = write(fd, ptr, nbytes)) == -1) {if (errno == EINTR)goto again;elsereturn -1;}return n; }int Close(int fd) {int n;if ((n = close(fd)) == -1)perr_exit("close error");return n; }

?

#ifndef __WRAP_H_ #define __WRAP_H_void perr_exit(const char *s); int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr); int Bind(int fd, const struct sockaddr *sa, socklen_t salen); int Connect(int fd, const struct sockaddr *sa, socklen_t salen); int Listen(int fd, int backlog); int Socket(int family, int type, int protocol); ssize_t Read(int fd, void *ptr, size_t nbytes); ssize_t Write(int fd, const void *ptr, size_t nbytes); int Close(int fd); ssize_t Readn(int fd, void *vptr, size_t n); ssize_t Writen(int fd, const void *vptr, size_t n); ssize_t my_read(int fd, char *ptr); ssize_t Readline(int fd, void *vptr, size_t maxlen);#endif
  • 服務端server.c
//server.c #include <unistd.h> #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <sys/wait.h> #include <ctype.h> #include <unistd.h> #include <sys/select.h> #include "wrap.h"#define SERV_PROT 6666int main(int argc, char *argv[]) {int i, j, n, nread;int maxfd = 0;int listenfd, connfd;char buf[BUFSIZ];struct sockaddr_in clie_addr, serv_addr;socklen_t clie_addr_len;listenfd = Socket(AF_INET, SOCK_STREAM, 0);int opt = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);serv_addr.sin_port = htons(SERV_PROT);Bind(listen, (struct sockaddr*)&serv_addr, sizeof(serv_addr));Listen(listenfd, 128);fd_set rset, allset;maxfd = listenfd;FD_ZERO(&allset);FD_SET(listenfd, &allset);while (1){rset = allset;nread = select(maxfd + 1, &rset, NULL, NULL, NULL); //每次循環都從新設置select監控信號集if(nread < 0)perr_exit("select error");if (FD_ISSET(listenfd, &rset)) //說明有新的客戶端連接請求{clie_addr_len = sizeof(clie_addr);connfd = Accept(listenfd, (struct sockaddr *)&clie_addr, &clie_addr_len);FD_SET(connfd, &allset); //向監控文件描述符集合allset添加新的文件描述符connfdif (maxfd < connfd)maxfd = connfd;if (0 == --nread) //說明select只返回一個,并且listenfd,后續執行無須執行continue;}for (i = listenfd + 1; i <= maxfd; i++){if (FD_ISSET(i, &rset)){if ((n = Read(i, buf, sizeof(buf))) == 0) //當client關閉鏈接時, 服務端也關閉對應鏈接{Close(i);FD_CLR(i, &allset); //解除select對此文件描述符的監控}else if(n == -1)perr_exit("read error");for (j = 0; j < n; ++j)buf[j] = toupper(buf[j]);Write(i, buf, n);}}}Close(listenfd);return 0; }
  • 客戶端:clent.c
#include <arpa/inet.h> #include "wrap.h"#define SERV_IP "192.168.245.139" #define SERV_PORT 6666int main(void) {int sfd, len;struct sockaddr_in serv_addr;char buf[BUFSIZ];sfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&serv_addr, sizeof(serv_addr));serv_addr.sin_family = AF_INET;inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);serv_addr.sin_port = htons(SERV_PORT);Connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));while (1) {fgets(buf, sizeof(buf), stdin);int r = Write(sfd, buf, strlen(buf));printf("Write r ======== %d\n", r);len = Read(sfd, buf, sizeof(buf));printf("Read len ========= %d\n", len);Write(STDOUT_FILENO, buf, len);}Close(sfd);return 0; }
  • 公共頭文件集程序:wrap.h、wrap.c

輸出結果:

客戶端:

服務端:

總結

以上是生活随笔為你收集整理的select函数(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。