zoukankan      html  css  js  c++  java
  • Linux 即时聊天系统(tcp)epoll 版

    简介:

      1.系统使用TCP来实现

      2.服务端 ctrl+d 能够使当前的客户端退出,但是服务端能够继续运行,并等待,响应其他的客户端的请求。ctrl+c 结束服务端进程

      3.ctrl+c 结束客户端进程

      4.服务器主要是用 epoll 模型实现,支持高并发

      <测试并可以正常运行>

      系统版本:Linux version 4.4.0-78-generic (buildd@lgw01-11) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4) )

     //头文件
    1
    #include <arpa/inet.h> 2 #include <sys/socket.h> 3 #include <netinet/in.h> 4 #include <stdio.h> 5 #include <netdb.h> 6 #include <string.h> 7 #include <sys/types.h> 8 #include <sys/socket.h> 9 #include <unistd.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <errno.h> 13 #include <sys/time.h> 14 #include <sys/epoll.h> 15 #include <signal.h>
      //服务端代码
    1
    #include"func.h" 2 3 int main(int argc,char *argv[]){ 4 //socket 5 int sfd = socket(AF_INET,SOCK_STREAM,0); 6 if(sfd == -1){ 7 perror("sfd"); 8 return -1; 9 } 10 //bind 11 struct sockaddr_in server; 12 memset(&server,0,sizeof(struct sockaddr_in)); 13 server.sin_family = AF_INET; 14 server.sin_port = htons(atoi(argv[2])); 15 server.sin_addr.s_addr = inet_addr(argv[1]); 16 int ret; 17 ret = bind(sfd,(struct sockaddr *)&server,sizeof(server)); 18 if(ret == -1){ 19 perror("bind"); 20 return -1; 21 } 22 //listen 23 ret = listen(sfd,10); 24 if(ret == -1){ 25 perror("listen"); 26 return -1; 27 } 28 29 printf("i am server "); 30 31 //epoll创建 32 int epfd = epoll_create(1); 33 34 struct epoll_event event,evs[3]; 35 //注册sfd 36 memset(&event,0,sizeof(event)); 37 event.events = EPOLLIN; 38 event.data.fd = sfd; 39 epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&event); 40 //注册0 41 memset(&event,0,sizeof(event)); 42 event.events = EPOLLIN; 43 event.data.fd = 0; 44 epoll_ctl(epfd,EPOLL_CTL_ADD,0,&event); 45 46 int ret1,i,len,new_fd; 47 char buf[128]={0}; 48 49 //新建client 50 struct sockaddr_in client; 51 while(1){ 52 memset(evs,0,sizeof(evs)); 53 int ret1 = epoll_wait(epfd,evs,3,-1); 54 if(ret1 > 0){ 55 for(i=0; i<ret1; i++){ 56 //sfd 有client请求建立里连接 57 if(evs[i].data.fd == sfd){ 58 memset(&client,0,sizeof(client)); 59 len = sizeof(client); 60 new_fd = accept(sfd,(struct sockaddr*)&client,&len); 61 if(new_fd == -1){ 62 perror("accept"); 63 return -1; 64 } 65 //注册new_fd 66 memset(&event,0,sizeof(event)); 67 event.events = EPOLLIN; 68 event.data.fd = new_fd; 69 epoll_ctl(epfd,EPOLL_CTL_ADD,new_fd,&event); 70 //打印客户端ip,端口 71 printf("client ip=%s,port=%d ",inet_ntoa(client.sin_addr),ntohs(client.sin_port)); 72 } 73 //0 服务端输入 74 if(evs[i].data.fd == 0){ 75 memset(buf,0,sizeof(buf)); 76 ret = read(0,buf,sizeof(buf)); 77 if(ret <= 0){ 78 printf("bye bye "); 79 close(new_fd); 80 //删除new_fd 81 memset(&event,0,sizeof(event)); 82 event.events = EPOLLIN; 83 event.data.fd = new_fd; 84 epoll_ctl(epfd,EPOLL_CTL_DEL,new_fd,&event); 85 break; 86 } 87 ret = send(new_fd,buf,strlen(buf)-1,0); 88 if(ret == -1){ 89 perror("send"); 90 return -1; 91 } 92 } 93 //new_fd 读客户端的数据 94 if(evs[i].data.fd == new_fd){ 95 memset(buf,0,sizeof(buf)); 96 ret = recv(new_fd,buf,sizeof(buf),0); 97 if(ret == -1){ 98 perror("recv"); 99 return -1; 100 }else if(ret == 0){ 101 printf("bye bye "); 102 close(new_fd); 103 //删除new_fd 104 memset(&event,0,sizeof(event)); 105 event.events = EPOLLIN; 106 event.data.fd = new_fd; 107 epoll_ctl(epfd,EPOLL_CTL_DEL,new_fd,&event); 108 break; 109 } 110 printf("%s ",buf); 111 } 112 } 113 } 114 } 115 close(sfd);//关闭sfd 116 close(new_fd);//关闭new_fd 117 close(epfd);//关闭epfd 118 return 0; 119 }

     //客户端代码(客户端并未使用epoll,有兴趣的可以自己进行修改)
    1
    #include"func.h" 2 3 int main(int argc,char *argv[]){ 4 //socket 5 int sfd = socket(AF_INET,SOCK_STREAM,0); 6 if(sfd == -1){ 7 perror("socket"); 8 return -1; 9 } 10 //connect 11 int ret; 12 struct sockaddr_in ser; 13 memset(&ser,0,sizeof(ser)); 14 ser.sin_family = AF_INET; 15 ser.sin_addr.s_addr = inet_addr(argv[1]); 16 ser.sin_port = htons(atoi(argv[2])); 17 ret = connect(sfd,(struct sockaddr*)&ser,sizeof(ser)); 18 if(ret == -1){ 19 perror("connect"); 20 return -1; 21 } 22 printf("i am client "); 23 char buf[128]={0}; 24 fd_set rdset; 25 while(1){ 26 FD_ZERO(&rdset); 27 FD_SET(0,&rdset); 28 FD_SET(sfd,&rdset); 29 ret = select(sfd+1,&rdset,NULL,NULL,NULL); 30 if(ret > 0){ 31 if(FD_ISSET(0,&rdset)){ 32 memset(buf,0,sizeof(buf)); 33 ret = read(0,buf,sizeof(buf)); 34 if(ret <= 0){ 35 printf("bye bye "); 36 break; 37 } 38 ret = send(sfd,buf,strlen(buf)-1,0); 39 if(ret == -1){ 40 perror("send"); 41 return -1; 42 } 43 } 44 if(FD_ISSET(sfd,&rdset)){ 45 memset(buf,0,sizeof(buf)); 46 ret = recv(sfd,buf,sizeof(buf),0); 47 if(ret == -1){ 48 perror("recv"); 49 return -1; 50 }else if(ret == 0){ 51 printf("bye bye "); 52 break; 53 } 54 printf("%s ",buf); 55 } 56 } 57 } 58 close(sfd); 59 60 return 0; 61 }
  • 相关阅读:
    leetcode 13. Roman to Integer
    python 判断是否为有效域名
    leetcode 169. Majority Element
    leetcode 733. Flood Fill
    最大信息系数——检测变量之间非线性相关性
    leetcode 453. Minimum Moves to Equal Array Elements
    leetcode 492. Construct the Rectangle
    leetcode 598. Range Addition II
    leetcode 349. Intersection of Two Arrays
    leetcode 171. Excel Sheet Column Number
  • 原文地址:https://www.cnblogs.com/24zyt/p/6880048.html
Copyright © 2011-2022 走看看