http://blog.csdn.net/robertkun/article/details/52269313
参考:http://www.cnblogs.com/Anker/p/3261006.html
使用poll实现的io多路复用服务端和客户端。
客户端通过子进程创建多个客户端连接。
客户端每隔1秒向服务端发送一个时间戳,
服务端接收到时间戳以后,保存在本地的文件中,
一个客户端对应一个存储文件,
并将接收到的时间戳返回给客户端。
代码:
服务端:
[cpp] view plaincopy
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <poll.h>
- #include <errno.h>
- #include <unistd.h>
- #include <sys/ioctl.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #define IP_ADDR "127.0.0.1"
- #define PORT 59999
- #define LISTEN_Q 5
- #define OPEN_MAX 100000
- #define INFTIM -1
- #define MAX_LINE 1024
- static int socket_bind(const char* ip, int port);
- static void do_poll(int ln_fd);
- static void handle_conn(struct pollfd* conn_fds, int num, int* files);
- int main()
- {
- int ln_fd, cn_fd, sk_fd = 0;
- struct sockaddr_in _addr;
- socklen_t _len;
- ln_fd = socket_bind(IP_ADDR, PORT);
- listen(ln_fd, LISTEN_Q);
- do_poll(ln_fd);
- return 0;
- }
- static int socket_bind(const char* ip, int port)
- {
- int ln_fd;
- struct sockaddr_in _addr;
- ln_fd = socket(AF_INET, SOCK_STREAM, 0);
- if(ln_fd == -1) {
- perror("socket error!");
- exit(1);
- }
- bzero(&_addr, sizeof(_addr));
- _addr.sin_family = AF_INET;
- inet_pton(AF_INET, ip, &_addr.sin_addr);
- _addr.sin_port = htons(port);
- if(bind(ln_fd, (struct sockaddr*)&_addr, sizeof(_addr)) == -1) {
- perror("bind error!");
- exit(1);
- }
- return ln_fd;
- }
- static void do_poll(int ln_fd)
- {
- int connfd, sockfd = 0;
- struct sockaddr_in _addr;
- socklen_t _len;
- int files[OPEN_MAX];
- struct pollfd clients[OPEN_MAX];
- int nMax, i, nReady = 0;
- clients[0].fd = ln_fd;
- clients[0].events = POLLIN;
- for(i = 1; i<OPEN_MAX; ++i) {
- clients[i].fd = -1;
- }
- nMax = 0;
- while(1) {
- nReady = poll(clients, nMax+1, INFTIM);
- if(nReady == -1) {
- perror("poll error!");
- exit(1);
- }
- else {
- printf("poll ready num = %d\n", nReady);
- }
- if(clients[0].revents & POLLIN) {
- _len = sizeof(_addr);
- if((connfd = accept(ln_fd, (struct sockaddr*)&_addr, &_len)) == -1) {
- if(errno == EINTR) {
- printf("EINTR!\n");
- continue;
- }
- else {
- perror("accept error!");
- exit(1);
- }
- }
- fprintf(stdout, "accept a new client! [%s]\n", inet_ntoa(_addr.sin_addr));
- for(i=1; i<OPEN_MAX; ++i) {
- if(clients[i].fd < 0) {
- fcntl(connfd, F_SETFL, fcntl(connfd,F_GETFL)| O_NONBLOCK);
- unsigned long nVal=1;
- ioctl(connfd, FIONBIO, &nVal);
- clients[i].fd = connfd;
- char path[2048] = {"\0"};
- getcwd(path, sizeof(path));
- sprintf(path, "%s/tmp_%d.txt", path, i);
- printf("path=%s\n", path);
- int fd = open(path, O_RDWR|O_APPEND|O_CREAT, 0666);
- if(fd > 0) {
- files[i] = fd;
- }
- else {
- fprintf(stdout, "open file error! [%s]\n", path);
- perror("open file error!");
- }
- break;
- }
- }
- fflush(stdout);
- if(i == OPEN_MAX) {
- fprintf(stderr, "too many clients\n");
- exit(1);
- }
- clients[i].events = POLLIN;
- nMax = (i > nMax ? i : nMax);
- if(--nReady <= 0) {
- printf("nReady = %d, nMax = %d\n", nReady, nMax);
- continue;
- }
- }
- handle_conn(clients, nMax, files);
- }
- }
- static void handle_conn(struct pollfd* conn_fds, int num, int* files)
- {
- int i, n = 0;
- char buf[MAX_LINE];
- memset(buf, 0, MAX_LINE);
- for(i=1; i<=num; ++i)
- {
- if(conn_fds[i].fd < 0)
- continue;
- if(conn_fds[i].revents & POLLIN) {
- n = read(conn_fds[i].fd, buf, MAX_LINE);
- if(n == 0) {
- close(conn_fds[i].fd);
- conn_fds[i].fd = -1;
- continue;
- }
- write(files[i], buf, n);
- write(conn_fds[i].fd, buf, n);
- }
- }
- }
客户端:
[cpp] view plaincopy
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <poll.h>
- #include <errno.h>
- #include <arpa/inet.h>
- #define MAX_LINE 1024
- #define IP_ADDR "127.0.0.1"
- #define SERV_PORT 59999
- #define max(a,b) (a>b)?a:b
- static void do_conn();
- static void handle_conn(int sockfd);
- int main(int args, char* argv[])
- {
- int i = 0;
- for(i=0; i<2000; ++i) {
- pid_t fpid = -1;
- fpid = fork();
- if(fpid < 0) {
- printf("error in fork!");
- }
- else if(fpid == 0) {
- do_conn();
- }
- else {
- //do_conn();
- }
- }
- return 0;
- }
- static void do_conn()
- {
- int sockfd;
- struct sockaddr_in _addr;
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- bzero(&_addr, sizeof(_addr));
- _addr.sin_family = AF_INET;
- _addr.sin_port = htons(SERV_PORT);
- inet_pton(AF_INET, IP_ADDR, &_addr.sin_addr);
- int ret = connect(sockfd, (struct sockaddr*)&_addr, sizeof(_addr));
- if(ret < 0) {
- perror("connect failed!");
- exit(1);
- }
- handle_conn(sockfd);
- }
- static void handle_conn(int sockfd)
- {
- char send_line[MAX_LINE] = {'\0'};
- char recv_line[MAX_LINE] = {'\0'};
- struct pollfd pfds[1];
- pfds[0].fd = sockfd;
- pfds[0].events = POLLIN|POLLOUT;
- while(1) {
- poll(pfds, 1, 1000);
- if(pfds[0].revents & POLLIN) {
- int ret = read(sockfd, recv_line, MAX_LINE);
- if(ret == 0) {
- perror("client: server is closed.");
- close(sockfd);
- continue;
- }
- else if(ret < 0) {
- perror("client: read error!");
- continue;
- }
- //printf("[%d] recv=%s\n", (int)getpid(), recv_line);
- }
- if(pfds[0].revents & POLLOUT) {
- time_t _time = time(0);
- char dt[20]={"\0"};
- sprintf(dt, "%d\n", _time);
- memcpy(send_line, dt, strlen(dt));
- int ret = write(sockfd, send_line, strlen(send_line));
- if(ret < 0) {
- perror("write error!!");
- }
- }
- sleep(1);
- }
- shutdown(sockfd, SHUT_WR);
- }