socket编程近期经验总结

最近在做的一个小项目,难度不大,但是网络传输部分费了一点周折,在这里把近期的一些经验教训总结一下。因为是自己的一点心得,如果有疏漏,后面再补充修正。

程序使用TCP协议传输,先epoll_wait(其实连接不多,只是熟悉一下,结果确实学到了东西),然后进行接收。因为TCP有流量控制,会把大的流进行分片,所以一次recv并不能接收全部的数据,刚开始就先接收一个header,包含了流的长度,然后再循环调用recv接收整个数据包。后来觉得这样太繁琐低级(而且经常发生接收错误),就想着怎样能一次把数据全部接收。

参考了一下项目中的代码,调用recvfrom就能一次接收,而不用先发送一个header,而且这个函数可以用于TCP和UDP。立马觉得这是个神器,尝试了一下,还是会有接收不完整的情况。思考了一下,项目中是UDP,不会进行“分片”,只要在长度那里填一个最大值,并且把系统的最大缓冲开大一点就可以了,而我现在是TCP,必然会分片,所以结果就不一样。

于是又返回recv。查了一下recv这个函数的说明,在flag中有MSG_WAITALL这个选项,可以保证接收完整,但是这样的话,就必须提前知道数据包的长度。暂时是填了一个较大的值,不足的数据padding补足,有些浪费。后面想着还是返回原来的老路,先发送一个header,然后再MSG_WAITALL进行接收。但是根据最开始的经验,多次接收的话,偶尔会接收到错误的数据包,不知是不是当时没有处理好,没有接收完整,导致有可读的信号没有消除,还得验证一下。

后记:今天验证了一下,没有问题。而且验证了一下epoll的EPOLLONESHOT选项,也没有问题。有一个奇怪的事情,有一次又是收到大量错误的header信息,修改socket为非阻塞后正常,但是后来不能重现问题了,非常费解。

看了一下项目中代码,也是先发送一个header(包含长度和flag),然后进行接收。不过他们调用的是ace中reactor等的类,所以代码还比较简洁。

接触linux好多年了,居然被这么低级的问题难住,真是难为情啊。。。。。

(后面补一下代码)

猜你喜欢

转载自onmyway-1985.iteye.com/blog/2380037