Closed qq1134993111 closed 4 years ago
1、看代码tcp都是同步发送的,是否可添加异步发送? 你可以再仔细看下,其实都是异步发送,而不是同步发送,同步发送的代码需要自己去写(很好写不考虑安全的话基本就一行代码)(因为同步发送需要考虑多线程同时发送时的安全问题,而异步发送中已经处理过此问题了) 2、另外tcp接收到消息的时候,如果不是整个消息包,应用程序还需要自己保存接收的数据,是否可以添加操作告诉回调函数处理了多少字节,还有多少字节没处理,让调用回调的函数自己处理没有使用的数据. 的确如此。我考虑一下吧。其实你想要处理这个问题完全可以用match_role的办法来解决(参考示例代码),无论是什么样的用户数据协议,都可以用match_role的策略来处理。经过match_role正确处理后的数据包一定是一个完整的数据包。
发送最终调用的asio::write,异步发送不是async_write吗?
发送最终调用的asio::write,异步发送不是async_write吗?
内部的确是同步发送的,但外部用户接口是异步的。内部用同步发送的原因是不想再添加一个额外的队列来保证async_write异步发送的安全,用asio::write的则不需要考虑该问题。
为什么内部要用同步发送:主要是考虑用户在发送数据时,数据可以是任意格式的,char*字符串,std::string std::vector等等,如果用异步,则这些数据必须要提前保存到一个队列里再顺序发送,那么这个队列该如何设计才能抹平这些类型差异呢,我始终没有解决这个问题,也不清楚这个问题到底能不能解决(如果在队列内部再造一个buffer,把这些类型复制到该buffer中也行,但这多了一次内存拷贝,无法接受),因此我经过了多次的调整尝试才选择用同步的,用同步这个问题很好处理,不管什么类型,一层层的传递下去即可。至于是用write还是async_write,其内部都是调用的WSASend(windows下),唯一的区别是write时,内部有一个select等待socket发送完毕的操作,这个select操作和异步来比到底有多大差异,我也不清楚。但我对write和async_write做过测试,发送数据的效率没比较出有何差异。
按理说同步发送的话,是写的socket发送缓冲区,如果客户端接收的慢,发送缓冲区满了就会堵.我觉得不应该支持那么多数据类型,内部确定一种buffer类型当作队列元素,作为标准接口,再提供几个常用地其他接口如char*,string,std::vector等,这几种接口做一次转换,转为buffer类型.如果使用者调用的是标准的buffer接口就可以直接move,如果是其他接口就转换一下,怎么使用让用户自己选择.
同步发送如果堵的话异步发送应该一样会堵。
如果没有确凿的证据或测试能证明async_write比write性能好,我不会去这样做的,丢失了外部接口的友好性而得不到性能提升,完全没有意义,而且内部还无法避免的多了一次内存拷贝。
你有兴趣的话可以写代码测试一下。
同步的话最好把soket设置为非阻塞的,测试客户端每秒发送1M的数据,服务端不接收,客户端发送几次后就堵在WSASend这里,导致io_context线程阻塞,后面的都无法处理。异步的话数据最多都堵在队列里,不触发回调,不至于把整个线程堵了。
有道理哦,同步阻塞的话会阻塞整个io_context线程。我好好想想,看能不能找到个好的解决办法。
已修复此问题 如果看到,请把这个issue关闭。
good
看代码tcp都是同步发送的,是否可添加异步发送?另外tcp接收到消息的时候,如果不是整个消息包,应用程序还需要自己保存接收的数据,是否可以添加操作告诉回调函数处理了多少字节,还有多少字节没处理,让调用回调的函数自己处理没有使用的数据.