一个epoll事件实现的高并发服务/客户端(C语言实现,服务端存储基于hashtable)

  代码路径:https://github.com/prophetss/epoll-event

  之前实现了一个简单高效的hashtable(点这里),之后一直想利用它再延伸一些功能,后来偶然看到一个hashtable与epoll事件的结合感觉效率很高所以自己尝试着实现了下。大体思想是将epoll接到的每一个服务请求存储到hashtable里来管理,每一个请求都可以设置独立的回调函数。具体可以先看代码,注释已经写得很详细。代码实现了一个简单实例,由于条件有限,client端我是fork了大量子进程来模仿高并发请求。性能测试我这几天有时间再搞下,大概试了下1s几十万次请求应该是可以的。暂时先写到这里,下面先贴一个client的源码充下大小..

  1 #include <unistd.h>
  2 #include <sys/mman.h>
  3 #include <netinet/in.h>
  4 #include <semaphore.h>
  5 #include <sys/types.h>
  6 #include <sys/socket.h>
  7 #include <arpa/inet.h>
  8 #include <fcntl.h>
  9 #include <wait.h>
 10 #include <string.h>
 11 #include <netdb.h>
 12 #include <stdlib.h>
 13 #include "error.h"
 14 
 15 
 16 /*进程共享文件用于统计创建进程个数*/
 17 #define PFILE_NAME    "count"
 18 
 19 
 20 struct shared {
 21     sem_t mutex;    /*信号量用于加锁*/
 22     int count;        /*进程个数*/
 23 } shared;
 24 
 25 
 26 void request(const char *server_ip, int server_port)
 27 {
 28     struct sockaddr_in client_addr;
 29     bzero(&client_addr, sizeof(client_addr));
 30     client_addr.sin_family = AF_INET;
 31     client_addr.sin_addr.s_addr = INADDR_ANY;
 32     client_addr.sin_port = htons(0);
 33     
 34     int client_socket = socket(AF_INET, SOCK_STREAM, 0);
 35     if(client_socket < 0) sys_exit_throw("create client socket fail");
 36     
 37     struct sockaddr_in server_addr;
 38     bzero((char *)&server_addr, sizeof(server_addr));
 39 
 40     server_addr.sin_family = AF_INET;
 41 
 42     struct hostent *server = gethostbyname(server_ip);
 43     if(!server) sys_exit_throw("fail to get host name");
 44 
 45     bcopy((char *)server->h_addr, (char *)&server_addr.sin_addr.s_addr, server->h_length);
 46 
 47     server_addr.sin_port = htons(server_port);
 48     socklen_t server_addr_len = sizeof(server_addr);
 49 
 50     if(connect(client_socket, (struct sockaddr*) &server_addr, server_addr_len) == -1 ) {
 51         sys_exit_throw("connent to server fail");
 52     }
 53 
 54     int pid = getpid();
 55 
 56     char content[64] = {0};
 57     sprintf(content, "%s, pid:%d", "i am client!", pid);
 58 
 59     send(client_socket, content, strlen(content), 0);
 60 
 61     close(client_socket);
 62 }
 63 
 64 /*
 65   参数1为serverip,参数2为server端口号
 66 */
 67 int main(int argc,char *argv[])
 68 {
 69     if(argc != 3) exit_throw("parameter error!\n");
 70 
 71     char *server_ip = argv[1];
 72     int server_port = atoi(argv[2]);
 73 
 74     struct shared *psh;
 75 
 76     /*创建共享文件*/
 77     int fd = open(PFILE_NAME, O_RDWR | O_CREAT, 0666);
 78     /*初始化*/
 79     write(fd, &shared, sizeof(struct shared));
 80     /*映射内存*/
 81     psh = mmap(NULL, sizeof(struct shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
 82     close(fd);
 83 
 84     sem_init(&psh->mutex, 1, 1);
 85 
 86     /*初始进程+1*/
 87     psh->count++;
 88     
 89     int i, status;
 90     for (i = 0; i < 10; i++) {
 91         pid_t fpid = fork();
 92         if (0 == fpid) {
 93             sem_wait(&psh->mutex);
 94             psh->count++;
 95             printf("%d processes have created!\n", psh->count);
 96             sem_post(&psh->mutex);
 97             request(server_ip, server_port);
 98         }
 99         else if (fpid > 0) {
100             request(server_ip, server_port);
101             wait(&status);
102         }
103         else
104             sys_exit_throw("fork error!");
105     }
106 
107     return 0;
108 }

猜你喜欢

转载自www.cnblogs.com/prophet-ss/p/9180977.html