上一篇文章介绍了基本的select模型,使用select模型编写了一个功能超级简单的echo服务器,可以同时监听一个套接口(用户接受客户端连接)和标准输入。对于每一个客户端连接都是输出客户端的内容后,立马终止与客户端的连接,这一片文章中,同时监听标准输入,监听的套接口与已连接的客户端。
srv.c
#include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/select.h> int conn[FD_SETSIZE] = {0, 1, 2}; int connNum = 3; int getPortFromParam(int argc, char *argv[]); int openListenfd(int port); int init_fdset(fd_set *fdset); void echo_cmd(); void process_new_connection(int listenfd); void process_cli(fd_set *fdset); int main(int argc, char *argv[]) { int port = getPortFromParam(argc, argv); int listenfd = openListenfd(port); conn[connNum++] = listenfd; fd_set fdset; while(1) { int maxfd = init_fdset(&fdset); int num = select(maxfd + 1, &fdset, NULL, NULL, NULL); if(num == -1) { //error perror("select error!"); exit(1); } else if( num == 0) { continue; //time out } else { if(FD_ISSET(0, &fdset)) { echo_cmd(); //stdin } if(FD_ISSET(listenfd, &fdset) ) { process_new_connection(listenfd); } process_cli(&fdset); } } return 0; } int getPortFromParam(int argc, char *argv[]) { if(argc != 2) { printf("%s <port>\n", argv[0]); exit(1); } int port = atoi(argv[1]); } int openListenfd(int port) { int listenfd = socket(AF_INET, SOCK_STREAM, 0); if(listenfd == -1) { perror("create socket error"); exit(1); } struct sockaddr_in socksrv; bzero(&socksrv, sizeof(socksrv)); socksrv.sin_family = AF_INET; socksrv.sin_port = htons(port); socksrv.sin_addr.s_addr = htonl(INADDR_ANY); int result = bind(listenfd, (struct sockaddr*)&socksrv, sizeof(socksrv)); if(result == -1) { perror("bind error"); exit(1); } result = listen(listenfd, 20); if(result == -1) { perror("listen error"); exit(1); } return listenfd; } int init_fdset(fd_set *fdset) { FD_ZERO(fdset); int i, max = 0; for(i = 0; i < connNum; i++) { FD_SET(conn[i], fdset); if(conn[i] > max) max = conn[i]; } return max; } void echo_cmd() { char buf[100] = {0}; int nread = read(STDIN_FILENO, buf, sizeof(buf)); if(nread == 0) { printf("%s\n", "exit"); int i = 3; for(; i < connNum; i++) close(conn[i]); exit(1); } else if(nread > 0) { printf("%s", buf); } } void process_new_connection(int listenfd) { int fd = accept(listenfd, NULL, NULL); if( fd == -1 ) { perror("accept error!"); exit(1); } else { conn[connNum++] = fd; printf("new connection:%d\n", fd); } } void process_cli(fd_set *fdset) { int i; for(i = 4; i<connNum; i++) { if(FD_ISSET(conn[i], fdset)) { char buf[100] = {0}; int nread = read(conn[i], buf ,sizeof(buf)); if(nread == 0) { //close close(conn[i]); printf("%d close!\n", conn[i]); if(i != connNum - 1) { conn[i] = conn[connNum - 1]; } --i; --connNum; } else if(nread > 0){ buf[strlen(buf)-1] = 0; printf("%d %s\n", conn[i], buf); } } } }
#include <sys/socket.h> #include <stdlib.h> #include <netinet/in.h> #include <string.h> #include <stdio.h> int main(int argc, char *argv[]) { if(argc != 2) { printf("%s <port>\n", argv[0]); exit(1); } int port = atoi(argv[1]); int fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in socksrv; bzero(&socksrv, sizeof(socksrv)); socksrv.sin_family = AF_INET; socksrv.sin_addr.s_addr = htonl(INADDR_ANY); socksrv.sin_port = htons(port); int result = connect(fd, (struct sockaddr*)&socksrv, sizeof(socksrv)); while(1) { char buf[100] = {0}; int nread = read(0, buf, sizeof(buf)); if(nread == 0) { close(fd); break; } else if(nread > 0) { write(fd, buf, strlen(buf)); } } return 0; }