18 | 防人之心不可无:检查数据的有效性
该思维导图由 AI 生成,仅供参考
对端的异常状况
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了网络编程中数据有效性的重要性以及相关技术细节。首先,文章提到了防范对端异常的方法,包括设置套接字的读操作超时和对连接是否正常的检测,以及利用多路复用技术自带的超时能力。其次,强调了缓冲区处理的重要性,指出设计良好的网络程序应该能够在随机输入的情况下表现稳定,并且需要时刻提醒自己面对各种复杂异常的场景,甚至是别有用心的攻击者。最后,通过具体的代码片段和实例,帮助读者更好地理解了网络编程中数据有效性的重要性和相关技术细节。文章内容深入浅出,通过具体的代码片段和实例,帮助读者更好地理解了网络编程中数据有效性的重要性和相关技术细节。文章内容深入浅出,通过具体的代码片段和实例,帮助读者更好地理解了网络编程中数据有效性的重要性和相关技术细节。
《网络编程实战》,新⼈⾸单¥59
全部留言(25)
- 最新
- 精选
- LDxy1,最终缓冲区的大小应该比预计接收的数据大小大一些,预防缓冲区溢出。2,完全可以动态分配,但是要记得在return前释放缓冲区
作者回复: 👍
2019-09-1233 - 郑祖煌(1).第一道,我们在读数据的时候,一般都需要给应用程序最终缓冲区分配大小,这个大小有什么讲究吗? 有讲究的。如果分配的太小,那就会频繁的从用户太切换到内核态,这样其实非常损耗CPU的时间。同时如果设置的太大的话,那就会长期阻塞在read或者recv函数上,造成可以先服务或者先完成的内容没完成。再次,也得比实际的数据稍微大一些以免缓冲区溢出,边界的问题要想办法做好的调整。。 (2). 第二道,你能分析一下,我们文章中的例子所分配的缓冲是否可以换成动态分配吗?比如调用 malloc 函数来分配缓冲区?是可以动态分配,就是new的话要记得及时的去delete,以免造成内存泄露。
作者回复: 回答的这么赞,我还能说啥呢 :)
2020-07-0221 - 超大红细胞一开始不理解为什么设置了 timeout 的 recv 会返回 EAGAIN 错误,在我的知识体系中 EAGAIN 一般出现在非阻塞的 socket 中,后来 man 了一下 SO_RCVTIMEO,发现确实如此,给后面的同学提个醒: Specify the receiving or sending timeouts until reporting an error. The argument is a struct timeval. If an input or output function blocks for this period of time, and data has been sent or received, the return value of that function will be the amount of data transferred; if no data has been transferred and the timeout has been reached then -1 is returned with errno set to EAGAIN or EWOULDBLOCK, or EINPROGRESS (for connect(2)) just as if the socket was specified to be nonblocking. 总之一句话,SO_RCVTIMEO 会导致 recv 返回 EAGAIN
作者回复: 👍
2020-01-1116 - 郭晓朋你好,对于最后一个例子我感觉好像有问题,--length这种写法会读不到012345678\n这个字符串的,最终导致读到的字符串没有结束符\0。length--导致越界的原因是*buffer++ = c;。不应该先执行buffer++,应该放到if语句之后。
作者回复: 你是说样例的readline程序有问题么?
2021-01-2822 - J.M.Liu老师,第二个例子中,及时加上了msg_length和缓冲区length的大小比较,如果msg_length写得很大(但小于length)而实际数据没有那么大时,服务器也会阻塞在read上吧?所以说判断msg_length<=length并不能接read阻塞的问题呀,只能解内存溢出的问题。
作者回复: 是的,如果是这样,只能说我们双方的通信协议没有得到严格的遵守。
2019-09-122 - 纪神籽第三个例子有点疑问,如果第一次调用readline,读取512字节,查到第100字节是换行符,然后就返回结果,这样子剩下的412字节不就会丢失了。是不是应该先把上次readline的数据处理完在进行新的recv。
作者回复: 你说的没错,是需要把剩下的412字节保存下来的。这个例子只是对readline该注意的事项进行了模拟分析。
2022-03-311 - 黄毅关于思考题的第二个问题,有个疑问,如果通过动态分配read_buffer,假设recv能读取512个字节,进一步假设第200个字符是\n,那么在read_line退出前能delete吗?如果delete的话,会不会第201到512字节的数据丢失?
作者回复: 这要看你的程序是怎么设计的,如果是预先读取了512字节,那确实200后的数据,你得想办法重新"缓冲"起来,以便和后面的数据拼凑成完整意义的字节流;如果你是一个一个字节读的,知道读到\n,那么则不必了。 一般情况下,我们是用缓冲来做这件事情,你可以跳到后面的Buffer设计部分,通过指针来指向当前消费的位置,和数据读取的位置做一个比较,就可以不用每次重新生成动态分配的buffer。
2021-04-101 - 无名氏临时缓存区,那个“微小瑕疵”,前后两段程序程序没有区别啊😄?
作者回复: 你细品: int nBytes = recv(connfd, buffer, sizeof(buffer), 0); int nBytes = recv(connfd, buffer, sizeof(buffer)-1, 0);
2022-05-22 - 苏志辉第三个例子修改后的版本,如果length为10发送的也是012345678\n一共10个,由于--length,所以一次最多读9个,要读完完整的消息,需要读两次吧
作者回复: 读取的时候,是一次性尝试读取最多 512 字节。 最外面的length循环实际上控制的是拷贝临时缓冲区字符的工作。 所以,还是读取一次。
2021-10-29 - 吃猫的鱼第三个例子中,如果recv读取出的数据格式如下 “xxx\n yyy\n”,然后length=4,此时在不就只读出 “xxx\n”,但是下一次调用recv,“yyy\n”没被应用就被丢弃了。。。
作者回复: 这个例子的假设就是\n为报文的分界符。
2021-08-06