1.五个简单TCP协议
-
MuduoManual.pdf P50
-
(1)echo - 回显服务,把收到的数据发回客户端
-
eg测试:42\jmuduo\examples\simple\echo\echo.h
42\jmuduo\examples\simple\echo\main.cc
42\jmuduo\CMakeLists.txt -
测试:客户端使用nc
服务端
客户端退出后,服务端一个TcpConnection销毁了
-
(2)discard - 服务器端收到客户端发送过来的数据,丢弃所有收到的数据;
-
eg:42\jmuduo\examples\simple\discard\discard.cc
-
(3)daytime - 服务端 accept 连接之后,以字符串形式发送当前时间,然后主动断开连接;
-
eg测试:42\jmuduo\examples\simple\daytime\daytime.cc
-
测试:
-
(4) time - 服务端 accept 连接之后,以二进制形式发送当前时间(从 Epoch 到现在的秒数),然后主动断开连接;我们需要一个客户程序来把收到的时间转换为字符串。
-
eg测试:
-
42\jmuduo\examples\simple\time\time.cc
42\jmuduo\examples\simple\timeclient\timeclient.cc -
测试:
服务端
客户端
-
(5)chargen(字符串生成协议,ASCII:33-126为可打印字符) - 服务端 accept 连接之后,不停地发送测试数据。
-
大致规律如下:
每一行都是72个字符,总共94行,下面是一组消息(即一个消息),每94行为一个单位
33 34 35 。。。104
34 35 36 。。。105
。。。
55 56 57 。。。126
56 57 58 。。。126 33
。。。
126 33 34 35 .0。。 103 -
eg:42\jmuduo\examples\simple\chargen\chargen.cc
42\jmuduo\examples\simple\chargenclient\chargenclient.cc -
eg测试:42\jmuduo\examples\simple\chargen\main.cc
-
测试:
客户端使用nc
服务端
吞吐量不是很大,因为TCP有流量调节的功能,即使服务端生成数据很快,但是客户端接收或者处理数据慢,则服务端就会调整它生成数据的速度,以更慢的频率发送数据。
-
eg测试:42\jmuduo\examples\simple\chargenclient\chargenclient.cc
42\jmuduo\examples\simple\chargen\main.cc -
测试:客户端
服务端的吞吐量就很高了,基本上把千M网卡跑满了,1000M/8=125Mb
2.muduo库网络模型使用示例
-
sudoku求解服务器MuduoManual.pdf P35
(1)reactor(一个IO线程)
(2)multiple reactor (多个IO线程)
(3)one loop per thread + thread pool (多个IO线程 + 计算线程池) -
eg:(1)reactor(一个IO线程)
42\jmuduo\examples\sudoku\server_basic.cc -
eg:(2)multiple reactor (多个IO线程)
42\jmuduo\examples\sudoku\server_multiloop.cc
42\jmuduo\muduo\net\TcpServer.cc -
eg:(3)one loop per thread + thread pool (多个IO线程 + 计算线程池)
42\jmuduo\examples\sudoku\server_threadpool.cc
42\jmuduo\muduo\net\TcpServer.cc
当前只有一个reactor,当reactor涉及到大量的计算,就应该将计算放到计算线程池ThreadPool来处理,处理完毕后,结果通过IO线程send发送给客户端。
-
总结:使用muduo库需要关注三个半事件:
连接建立;
连接断开;消息到达;
消息发送完毕(对于低流量的服务来说,通常不需要关注该事件)
(1)reactor(一个IO线程)
提供一个XXXXServer类,在该类中包含一个TcpServer对象;
OnConnection:包含连接建立和连接断开
OnMessage:消息到达
OnWriteComplete:消息发送完毕
(2)要实现multiple reactor 模式(IO线程有多个),此时只需要增加server_setThreadNum(numThreads);,又进而调用EventLoopThreadPool::setThreadNum
(3)若增加计算线程池来计算计算密集型的服务,则在编写的XXX服务器中,增加一个ThreadPool threadPool_;//计算线程池对象,threadPool_.start(numThreads_);启动若干线程,threadPool_.run(boost::bind(&solve, conn, puzzle, id));来处理计算任务,通过conn->send(result+“\r\n”);IO线程来发送计算的结果