- 论坛徽章:
- 2
|
本帖最后由 yaoyefengyun 于 2015-04-25 18:41 编辑
学习了lvyilong316前辈的 《彻底学会使用epoll》系列,我现在想做成多线程,但又不是一个线程监听事件,其它几个线程负责事务处理那种。用一个连接测试,没测出问题,但是模拟1000个客户端时,服务端老有Bad file descriptor错误。之前服务端采用单个线程时,测试程序也没测出问题。大家帮我看看是代码写错了呢?还是说连思路都不正确。
下面是服务端代码:- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/epoll.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <pthread.h>
- #define MAX_EVENTS 2000
- #define SERV_PORT 9127
- #define MAXLINE 1024
- #define handle_error(msg) \
- do { perror(msg); exit(EXIT_FAILURE); } while (0)
- int epollfd, listenfd;
- pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- void setnonblocking(int fd)
- {
- int flags, ret;
- flags = fcntl(fd, F_GETFL, 0);
- if (flags == -1)
- handle_error("fcntl");
- ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
- if (ret == -1)
- handle_error("fcntl");
- }
- int create_and_bind(void)
- {
- int listenfd, err;
- struct sockaddr_in servaddr;
- listenfd = socket(AF_INET, SOCK_STREAM, 0);
- if (listenfd == -1)
- handle_error("socket");
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(SERV_PORT);
- servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
- err = bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
- if (err == -1)
- handle_error("bind");
- return listenfd;
- }
- void *thr_func(void *arg)
- {
- int i, nfds, connfd, ret;
- socklen_t clilen;
- ssize_t n, nread, nwrite, data_size;
- char buf[MAXLINE];
- struct sockaddr_in cliaddr;
- struct epoll_event ev, events[MAX_EVENTS];
- for ( ; ; ) {
- nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
- if (nfds == -1)
- handle_error("epoll_wait");
- for (i = 0; i < nfds; ++i) {
- if (events[i].data.fd == listenfd) {
- for ( ; ; ) {
- clilen = sizeof(cliaddr);
- connfd = accept(events[i].data.fd,
- (struct sockaddr *)&cliaddr,
- &clilen);
- if (connfd == -1) {
- if (errno == EAGAIN)
- break;
- else if (errno == ECONNABORTED||
- errno == EPROTO ||
- errno == EINTR)
- continue;
- else
- handle_error("accept");
- }
- if (connfd >= MAX_EVENTS) {
- ret = close(connfd);
- if (ret == -1)
- handle_error("close");
- continue;
- }
- setnonblocking(connfd);
- ev.data.fd = connfd;
- ev.events = EPOLLIN | EPOLLET;
- ret = epoll_ctl(epollfd,
- EPOLL_CTL_ADD, connfd, &ev);
- if (ret == -1)
- handle_error("epoll_ctl");
- }
- continue;
- }
- if (events[i].events & EPOLLIN) {
- n = 0;
- while ((nread = read(events[i].data.fd, buf + n,
- MAXLINE)) > 0)
- n += nread;
- if (nread == 0) {
- ret = close(events[i].data.fd);
- if (ret == -1)
- handle_error("close");
- continue;
- } else if (nread == -1 && errno != EAGAIN) {
- perror("read");
- continue;
- }
- ev.data.fd = events[i].data.fd;
- ev.events = EPOLLOUT | EPOLLET;
- ret = epoll_ctl(epollfd, EPOLL_CTL_MOD,
- events[i].data.fd, &ev);
- if (ret == -1)
- handle_error("epoll_ctl");
- }
- if (events[i].events & EPOLLOUT) {
- snprintf(buf, sizeof(buf),
- "HTTP/1.1 200 OK/r/n Content-Length: "
- "%d/r/n/r/nHello World",
- 11);
- data_size = strlen(buf);
- n = data_size;
- while (n > 0) {
- nwrite = write(events[i].data.fd,
- buf + data_size - n , n);
- if (nwrite == -1 &&
- errno != EAGAIN)
- handle_error("write");
- n -= nwrite;
- }
- ev.data.fd = events[i].data.fd;
- ev.events = EPOLLIN | EPOLLET;
- ret = epoll_ctl(epollfd, EPOLL_CTL_MOD,
- events[i].data.fd, &ev);
- if (ret == -1)
- handle_error("epoll_ctl");
- }
- }
- }
- }
- int main(void)
- {
- int i, ret;
- struct epoll_event ev;
- pthread_t tid[4];
- listenfd = create_and_bind();
- setnonblocking(listenfd);
- ret = listen(listenfd, MAX_EVENTS);
- if (ret == -1)
- handle_error("listen");
- epollfd = epoll_create1(0);
- if (epollfd == -1)
- handle_error("epoll_create");
- ev.events = EPOLLIN | EPOLLET;
- ev.data.fd = listenfd;
- ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev);
- if (ret == -1)
- handle_error("epoll_ctl");
- for (i = 0; i < 4; i++) {
- ret = pthread_create(&tid[i], 0, thr_func, 0);
- if (ret != 0)
- handle_error("pthread_crete");
- }
- for (i = 0; i < 4; i++) {
- ret = pthread_join(tid[i], 0);
- if (ret != 0)
- handle_error("pthread_jion");
- }
- exit(EXIT_SUCCESS);
- }
复制代码 下面是客户端测试代码:- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <pthread.h>
- #include <signal.h>
- #define MAXLINE 8192
- #define LISTENQ 1024
- #define SERV_PORT 9127
- #define handle_error(msg) \
- do { perror(msg); exit(EXIT_FAILURE); } while (0)
- #define err_quit(msg) \
- do { fprintf(stderr, msg); exit(EXIT_FAILURE); } while (0)
- void str_cli(FILE *fp, int sockfd)
- {
- pid_t pid;
- int n, ret;
- char sendline[MAXLINE + 1], recvline[MAXLINE + 1];
- pid = fork();
- switch (pid) {
- case -1:
- handle_error("fork");
- break;
- case 0:
- while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
- recvline[n] = 0;
- fprintf(stderr, recvline);
- }
- kill(getppid(), SIGTERM);
- exit(0);
- break;
- default:
- while (fgets(sendline, MAXLINE, fp))
- write(sockfd, sendline, strlen(sendline));
- break;
- }
- ret = shutdown(sockfd, SHUT_WR);
- if (ret == -1)
- handle_error("shutdown");
- }
- void *thr_func(void *arg)
- {
- int sockfd, ret;
- ssize_t s;
- struct sockaddr_in servaddr;
- char buf[MAXLINE];
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (sockfd == -1)
- handle_error("socket");
- bzero(&servaddr, sizeof(servaddr));
- servaddr.sin_family = AF_INET;
- servaddr.sin_port = htons(SERV_PORT);
- ret = inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
- if (ret == -1)
- handle_error("inet_pton");
- ret = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
- if (ret == -1)
- handle_error("connect");
- s = write(sockfd, "echo", 4);
- if (s == -1)
- fprintf(stderr, "%ld, write %s\n",
- (long)pthread_self(), strerror(errno));
- ret = shutdown(sockfd, SHUT_WR);
- if (ret == -1)
- handle_error("shutdown");
- s = read(sockfd, buf, MAXLINE);
- if (s == -1)
- fprintf(stderr, "read %s\n", strerror(errno));
- return NULL;
- }
-
- int main(void)
- {
- int i, ret;
- pthread_t tid[1000];
- for (i = 0; i < 1000; i++) {
- ret = pthread_create(&tid[i], 0, thr_func, 0);
- if (ret != 0)
- handle_error("pthread_create");
- }
- for (i = 0; i < 1000; i++) {
- ret = pthread_join(tid[i], NULL);
- if (ret != 0)
- handle_error("pthread_join");
- }
- exit(EXIT_SUCCESS);
- }
复制代码 |
|