在学习linux 并发非阻塞服务器时候。看到有使用poll 函数的方式。初步理解并编写程序进行了测试。
服务器:
#include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definitions */ #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ #include <arpa/inet.h> /* inet(3) functions */ #include <poll.h> #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <string.h> #define MAX_LINK 10 int main() { struct sockaddr_in server_addr,client_addr; bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(6888); socklen_t socklen = sizeof(struct sockaddr_in); int ser_fd,con_fd; ser_fd=socket(AF_INET, SOCK_STREAM, 0); if(bind(ser_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in)) == -1) { perror("bind error"); exit(-1); } if (listen(ser_fd,10) < 0) { perror("listen error"); return -1; } struct pollfd fds[MAX_LINK]; fds[0].fd=ser_fd; fds[0].events=POLLRDNORM; int i=1; for(;i<MAX_LINK;i++){ fds[i].fd=-1; fds[i].events=POLLRDNORM; } int ready_n; int link_count=1; char buffer[1024]; while(1){ ready_n=poll(fds,link_count,-1); if(ready_n==-1){ printf("poll error \n"); return 0; } if(fds[0].revents & POLLRDNORM){ int cli=accept(ser_fd, (struct sockaddr*) &client_addr, &socklen); for(i=1;i<MAX_LINK;i++){ if(fds[i].fd<0){ fds[i].fd=cli; printf("new connect : %d \t",i); printf("%d\n",link_count); break; } } link_count++; ready_n--; } for(i=1;i<MAX_LINK && ready_n>0;i++){ if(fds[i].fd >0){ if(fds[i].revents & POLLRDNORM){ int n=recv(fds[i].fd,buffer,1024,0); if(n==0){ fds[i].fd=-1; link_count--; }else if(n>0){ send(fds[i].fd,buffer,n,0); } ready_n--; } } } } return 0; }
客户端:
#include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definitions */ #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ #include <arpa/inet.h> /* inet(3) functions */ #include <sys/select.h> /* select function*/ #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <string.h> #define MAXLINE 10240 #define max(a,b) ((a) > (b) ? (a) : (b)) //typedef struct sockaddr SA; void handle(int sockfd); int main(int argc, char **argv) { char * servInetAddr = "127.0.0.1"; int servPort = 6888; char buf[MAXLINE]; int connfd; struct sockaddr_in servaddr; if (argc == 2) { servInetAddr = argv[1]; } if (argc == 3) { servInetAddr = argv[1]; servPort = atoi(argv[2]); } if (argc > 3) { printf("usage: selectechoclient <IPaddress> <Port>\n"); return -1; } 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) { perror("connect error"); return -1; } printf("welcome to selectechoclient\n"); handle(connfd); /* do it all */ close(connfd); printf("exit\n"); exit(0); } void handle(int connfd) { FILE* fp = stdin; char sendline[MAXLINE], recvline[MAXLINE]; fd_set rset; FD_ZERO(&rset); int maxfds = max(fileno(fp), connfd) + 1; int nread; for (;;) { FD_SET(fileno(fp), &rset); FD_SET(connfd, &rset); if (select(maxfds, &rset, NULL, NULL, NULL) == -1) { perror("select error"); continue; } if (FD_ISSET(connfd, &rset)) { //接收到服务器响应 nread = read(connfd, recvline, MAXLINE); if (nread == 0) { printf("server close the connection\n"); break; } else if (nread == -1) { perror("read error"); break; } else { //server response write(STDOUT_FILENO, recvline, nread); } } if (FD_ISSET(fileno(fp), &rset)) { //标准输入可读 if (fgets(sendline, MAXLINE, fp) == NULL) { //eof exit break; } else { write(connfd, sendline, strlen(sendline)); } } } }