epoll实现多人聊天小项目

本文详细介绍了一个基于C/S模式的多人聊天程序设计流程,包括TCP连接、epoll机制、父子进程通信、TCP/IP通信机制及epoll工作方式。深入探讨了服务器端与客户端的套接字操作、连接管理、数据收发及关闭过程。

多人聊天项目的流程:

1基于C/S模式建立的多人聊天程序,首先实现单一客户端与服务器的TCP连接。

2然后运用epoll机制实现多人聊天。这里的多人聊天指的是群聊,每个用户可以发消息到服务器,然后可以从服务器收到其他的用户的消息。

3这里fork()子进程,子进程等待接受用户输入的信息,然后把信息输入到管道,传给父进程。父进程把用户的消息传送到服务器,然后接受服务器传来的其他的用户的消息。

4.TCP/IP机制,服务器端,服务器创建套接字,绑定套接字,监听绑定的套接字,链接客户端的套接字,连接上之后等待客户端传来的数据,然后给客户端响应,最后关闭链接。客户端,建立套接字,连接服务器,发送请求,接受应答,关闭链接。TCP/IP通信结束。

如果阻塞的话服务器端在accept()阻塞,等待客户端建立连接。

5.epoll机制,就是先创建套接字,把注册好的套接字用函数调用到内核的事件表中,然后函数调用把就绪的事件放到就绪列表中。并对就绪的套接字进行判断,如果是客户端建立连接的套接字,那么进行连接,并添加到就绪描述符如果是已建立好的客户端连接传来的数据套接字,则打印输出数据。

6.采用ET模式,设置描述符事件都为非阻塞方式,这样可以连接多个描述符事件,而不是连接上了一台客户机或者文件描述符之后一直处于等待状态。阻塞方式就是视图对该文件描述符进行读写时,如果当前没有数据可读,或者暂时不可写,程序进入等待状态,直到有东西读或者写为止,这样耗费服务器资源,并且效率提高不少

补充:epoll有两种工作方式,LT(level triggered):水平触发和ET(edge-triggered):边沿触发。LTselect/poll使用的触发方式,比较低效;而ETepoll的高速工作方式(本项目使用epollET方式)。

这里的TCP/IP连接是第一步,面试会问到:

TCP/IP通信

服务器端

  1. int Socket(int domain,int types,int protocal);//domain指的是那个底层协议族ipv4/ipv6; types指的是数据传输方式SOCK_SCREAM,SOCK_UGRAM; protocal默认为0。
  2. int Bind(int sockd,const struct sockaddr* addr,sizeof(saddr));//与地址绑定,叫套接字的命名,服务器端要命名,客户端连接的时候知道连接那个套接字,而客户端不需要,匿名就可以。成功是0,失败是-1。并且是error。出错一般两种,一是(0~1023)接口一般是不能绑定的,系统固定,超级用户访问;二是,端口处于time_wait状态,不能绑定。
  3. int listen(int sockfd,int backlog);  //监听套接字,套接字命名之后,不能立马链接。系统创建一个监听队列来存放客户端的链接。Sockfd套接字,backlog为监听队列的个数。
  4. int accept(int sockfd,const struct backlog* addr,socklen_t *addrlen);//sockfd是系统执行过监听之后的sockfd; addr是远端的sockfd(一般客户端)。失败返回-1。也可以说服务器是通过listen调用被接受连接。

   5. int recv(int sockfd,void* buff,size_t len,int flags); //接受客户端的消息,buff缓冲区,len缓冲区的大小,flag一般为0。如果recv返回的值小于len,则可以多次调用,recv返回值为0时,就是对方关闭连接了。

  6.int send(int sockfd,const void* buff,size_t len,int flags); // 向客户端发送消息,也就是向sockfd上写数据,buff缓冲区长度len,失败返回-1。

 7.Int Close(int sockfd);//关闭连接。

 

Sockfd两个要素,一个IP地址,一个端口号

这里的sockfd是全双工的,对于双方而言的。

Netstat 命令查看通信过程时服务器的状态信息。

Tcpdump 命令可抓包,获取通信TCP报文段。

 

客户端

1.sockfd

2.Int Connect(int sockfd,const struct sockaddr* ser_addr,socklen_t addr);//这里的socket是客户端创建的socket(); 而serv_addr就是服务器监听的sockfd;最后是sockfd的长度。链接成功返回0,客户端和服务器就可以通过这个链接来建立通信;失败返回-1,可能目标端口不存在,也可能连接超时。

3.send()

4.recv()

5.Int Close(int sockfd);//关闭连接

这里顺带提一下Select poll epoll的区别

Select 和poll性能没有本质的区别,都是轮序的查找就绪的描述符,时间复杂度O(n)。select更复杂一些,select先要遍历描述符数组,查找有事件的描述符,再把查找到的描述符加入到内核事件表中。只是select的默认的描述符数组大小是1024,但是也可以修改,而poll的事件描述符是结构体结构,每次把事件结构体传入内核事件表,内核还要遍历事件表,找出就绪的描述符。 那poll解决了那些问题呢,poll是增大了描述符的数量,书上说是65535,但是也不绝对哈。明显的这里poll解决的事件比select多了,另一方面,select的事件只是读,写,异常。Poll处理的事件还有挂起,数据的优先级区分,错误等。

Epoll是Linux才有的,解决的问题主要是性能问题,时间复杂度是O(1)。直接在内核中添加,修改,删除描述符。这里是一组函数调用,内核创建事件表,有了事件之后,直接添加到内核。这里用调度函数直接调用就绪的描述符,没有时阻塞。这里是内核函数调度事件,不用轮序遍历,而epoll能处理的事件就更多了。

代码就不上附上了,有心的伙伴私聊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值