1.聊天服务器
-
聊天服务器(MuduoManual.pdf P66)
(1)examples/asio/chat/server.cc 单线程
(2)examples/asio/chat/server_threaded.cc,多线程TcpServer,并用mutex来保护共享数据mutex,由于mutex的存在,多线程并不能并发执行
(3)examples/asio/chat/server_threaded_efficient.cc,借shared_ptr实现copy-on-write的手法来降低锁竞争
(4)examples/asio/chat/server_threaded_highperformance.cc,采用thread local变量实现多线程高效转发 -
聊天服务器示意图
服务端收到客户端的hello消息,服务端转发hello消息到C1,C2,C3客户端
2.消息格式
- 消息分为包头与包体,每条消息有一个4字节的头部,以网络序存放字符串的长度。包体是一个字符串,字符串也不一定以’\0’结尾。比方说有两条消息"hello"和"chenshuo",那么打包后的字节流是:
- 0x00,0x00,0x00,0x05, ‘h’,‘e’,‘l’,‘l’,‘o’,0x00,0x00,0x00,0x08,‘c’,‘h’, ‘e’,‘n’,‘s’,‘h’,‘u’,‘o’
共21字节。
对于传输层来讲这是一个字节流,是没有边界的。在应用层将其解析出来,解析成2条消息,先解析包头,再解析包体,这才是一条完整的消息
3.时序图
-
coder decoder组合以下就是codec编解码,前者取前2个字符,后者取前3个字符;
LengthHeaderCodec就是对聊天服务器的消息进行编解码;
(1)当可读事件到来,回调LengthHeaderCodec中的onMessage,然后对收到的消息进行解码decode,先解析包头,再解析包尾,然后再把包体的字符串传给ChatServer,回调onStringMessage;
()ChatServer收到消息,将其转发给在线的客户端,调用LengthHeaderCodec::send(),因为要进行编码(包头+包体),send(Buffer)发送给在线的客户端
-
eg:44\jmuduo\examples\asio\chat\server.cc----------单线程版本
44\jmuduo\examples\asio\chat\codec.h
44\jmuduo\examples\asio\chat\client.cc
44\jmuduo\examples\asio\chat\server_threaded.cc----------多线程版本 -
eg测试:单线程:44\jmuduo\examples\asio\chat\server.cc
44\jmuduo\examples\asio\chat\client.cc -
测试:服务端
客户端1
客户端2
4.通过编程技巧降低锁竞争和提高并发效率
-
问题:45\jmuduo\examples\asio\chat\server_threaded.cc,多线程TcpServer,并用mutex来保护共享数据mutex,由于mutex的存在,多线程并不能并发执行,而是串行的。因而存在较高的锁竞争,效率比较低。
(1)eg:C1向服务器端发送一条消息hello,服务器通过一个IO线程转发给所有的客户端,与此同时C2向服务器端发送一条消息hello2,服务器端通过另一个IO线程转发给所有客户端,由于锁的存在,这两个线程并不能并发执行,而是串行的。这个时候,客户端数目比较大,第二条消息hello2到达各个客户端的延迟也比较大。
(2)大并发的一个杀手就是锁竞争 -
examples/asio/chat/server_threaded_efficient.cc,借shared_ptr实现copy-on-write的手法来降低锁竞争
(1)shared_ptr是引用计数智能指针,如果当前只有一个观察者,那么引用计数为1,可以用shared_ptr::unique()来判断(为真引用计数为1,否则不为1;shared_ptr共享资源既有读端,也有写端)
(2)对于write端,如果发现引用计数为1(只有一个写者来访问它),这时可以安全地修改对象,不必担心有人在读它。
(3)对于read端,在读之前把引用计数加1,读完之后减1,这样可以保证在读的期间其引用计数大于1,可以阻止并发写。
(4)比较难的是,对于write端,如果发现引用计数大于1,该如何处理?既然要更新数据,肯定要加锁,如果这时候其他线程正在读,那么不能在原来的数据上修改,得创建一个副本,在副本上修改,修改完了再替换。如果没有用户在读,那么可以直接修改。 -
eg:45\jmuduo\examples\asio\chat\server_threaded_efficient.cc
45\jmuduo\examples\asio\chat\server_threaded_highperformance.cc