这篇文章所要讲的局域网聊天工具是基于udp协议的,至于为什仫要使用udp协议,当然是为了更加深入的理解socket套接字编程了。有的读者就会问了那你为什仫不用tcp协议呢?因为之前已经写过了一个关于tcp协议的项目了啊。 http服务器
一、聊天室的原理
这个聊天室是可以达到类似QQ群聊的目的的。客户端向服务器发送消息,服务器将这条消息进行转发(转发其实就是利用了生产者消费者模型,生产者从网络中抓取数据,消费者向网络中发数据)。之前提到了用的是udp协议,所以服务器会维护一张用户列表,在这个用户列表中保存了向服务器发送消息的客户的信息(包括该用户的昵称、学校、发送的消息正文),当有新用户到来的时候会更新该用户列表。当有用户退出的时候,该用户会向服务器发送一条特殊的指令,将其从用户列表中删除。
二、聊天工具的实现机制
服务器
1、用户列表
因为使用的是udp协议,所以该服务器要维护一张用户列表,所谓的用户列表其实使用的是STL中的map,IP做key,sockaddr_in做value。
2、数据池
其实数据池就是用来存放数据的,生产者往数据池里面放数据,消费者从该数据池中获得数据。实际上就是上面原理图中的环形队列。数据池可以选取STL中的vector或者是list,我选的是vector;同时也要考虑生产者和消费者线程数据同步的问题。
客户端
3、客户端的界面–>ncurses
我为客户端编写的一个简单的界面,在这里用到了ncurses界面库,将屏幕切分成四部分,见下图:
在窗口类中明确定义了如何画出这四个区域,窗口类的定义如下:
4、维护这四个窗口的是四个线程,在代码内部实现。
5、序列化与反序列化–>json
为什仫要进行序列化呢?试想一下你在QQ群里聊天你发送了一条消息却没有显示是谁发的,这是不是很奔溃,想找好友都找不到了。。。此时可以给客户端设置了多个信息。序列化就是将用户的信息和从数据区域输入的消息进行组装成一个字符串,反序列化就是将这一个字符串拆分成若干信息。
用户的数据类型:
6、客户端如何退出
可以看到在数据类型的类中定义了cmd这个参数,就是用来存储用户退出信号的。可以注册一个信号处理函数,在信号处理函数中将cmd字段的值设置为非空,服务器拿到数据的时候,先反序列化解析出cmd的值,判断是不是退出的信息,如果是的话就将该用户从用户列表删除。
三、操作界面
点击查看源码
在这里就分享结束了~~~