Linux聊天室应用的实现(基于TCP和EPOLL,有TCP重连功能)

linux 同时被 2 个专栏收录
3 篇文章 0 订阅
1 篇文章 0 订阅

缘由

偶然有时间写写文章。
这个小实验起源是出于某个类似于面试题目。总之,是需要做完的,而做完之后不妨分享一下,肯定有很多不足,还请大家指正,交流。

要求大概说一下:
1.聊天室,需要有多个房间(channel或room)。
2.在房间中有禁言或者禁入的功能。
3.在客户端断网的情况下,恢复后可以重连到相应的房间。
4.c或c++,linux上实现。

https://github.com/LJNL/ChatServerAndChatRoom

先说缺点:
非正常退出的情况下,(比如ctrl+c):
服务端崩溃之后,客户端可以选择尝试重新连接,等服务器重启,即可继续。但服务端没有做持久化,服务器的数据(房间,客户信息丢失)。

客户端崩溃之后,服务端存有客户端信息,是不会清除的。由于客户端没有做持久化,即客户数据不会保存,因此服务端的资源还是被占用着。有人可能会说,那么我们在客户端崩溃的时候,清除一下资源不行吗?显然是可以的,但是作为服务端,很难分辨客户端是断网还是崩溃,断网时显然需要保持这份资源的。(注意很难只是个感叹词,也就是说,要做清理,先要搞个花招分辨一下两种情况,至于花招留给大家去思考了)。是否清理何时清理,留到持久化之后吧。

总之,看上面的要求,不难发现,持久化并不必要,所以有缘在做吧。

另外,感谢Sixzeroo提供的聊天室思路。

整体框架

整体框架,谈到聊天室那肯定要socket。socket一番多个客户端,socket太多了,需要一个管理机制,那么就选EPOLL吧。在此效率什么的不是重点,为什么选EPOLL,只是想了解一下EPOLL怎么用而已。至于socket的细节用法呀,EPOLL的实现细节用法呀,不是本文要介绍的。

从使用者的角度看,EPOLL就像打地鼠的游戏,每当接到新的连接把fd(文件描述符)做个洞,轮询着他,当有地鼠(事件)从那个洞里凸出来了,哪里凸了砸哪里。

至于怎么砸如何砸,待到后续再说。
只是注意close(fd)后,fd引用计数归零后,在EPOLL里面的fd会自动去掉的,并不用主动去管理。

功能上要求,多个聊天室或者多个频道呀多个房间呀。从服务端的角度,那我们要受理聊天室的创建,就像是一块空地,方方正正地种一模一样的树苗,按部就班来就好。但这涉及到资源了,最好来个标志,对每块地标记一番,是否有树。而每棵树呢,又会有谁种的(把TA当群主吧),谁会来灌水(群众),都通通记录一番。

而聊天的行为呢,谁去广播呢,叫树去广播吗,自然是可以的,但为了把这种消息收发的行为单独抽出来,也许是方便调试,也许就单纯试试,总而言之,在空地旁,安置了一个大喇叭,让这个大喇叭去做这种消息的传递,当有人来灌水,会有一个喇叭管理者过去表扬灌水者的丰功伟绩,用这个大喇叭广播一番,当然这个广播的频道是只有对那棵树灌过水的人才能收到。

而从客户端的角度来看,仅仅是个灌水的人,那么灌水分两步,第一步,种树或找树,第二步,灌水。

回到原题,
至于开关门(),改名()这些内容,只要在单独的房间概念上做些手脚就好。因为开关门,改名,只关系到个人和房间。

断网重连,
先说断网TCP连接不一定会断,TCP是有状态的,这点不展开。但时间长了之后会断的。此时网络又恢复了,客户端怎么做到回归之前的聊天房间呢。一种思路是需要一个可以在断开之前和恢复之后一直不变的东西,啥能一直不变呢。TCP连接断开连接fd就失效了,起码fd不能。没有什么的话,就无中生有吧,来个QQ号不香吗。那么我们可以在建立连接的时候就预先分配一个号码,让两者一直保持吧,海枯石烂,夏雨雪,除非一方突然挂掉(意外事故)或者协商后和平分手(正常退出),不然不变的。

如果意外发生,SIGPIPE信号就起作用了,Linux上的进程在收到信号时会异步执行信号处理函数。在此不讲它的细节部分,只是提示一点
当写信号处理函数一定要做到异步安全,比如像printf之类的函数是不能用的,缓冲区要预先分配的。

当然,服务端和客户端都需要SIGPIPE处理函数,他们都要防止一方崩溃,而引起另一方进程结束。

客户端状态图

客户端与服务端采用的是请求响应的方式。客户端涉及到状态,稍稍繁琐一些。服务端则提供相应服务就好。比如客户连接,服务应答分配ID;客户发消息,服务广播;不再赘叙。
下图为客户端状态,分为5个状态,状态之间的转移中分别对应一轮 请求–响应 之后得到的新的状态。
在这里插入图片描述

  • 1
    点赞
  • 1
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值