套接字的读写操作在阻塞、非阻塞模式下的表现
2021/8/23 23:36:16
本文主要是介绍套接字的读写操作在阻塞、非阻塞模式下的表现,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
背景
- 了解套接字的读写操作在阻塞模式、非阻塞模式下的表现会有差异,但是不知道
read()
、write()
操作套接字时具体的效果; read()
想要读取的数据字节数并不一定等于实际读取到的字节数,如何使读操作实际读取的字节数与想要获取的字节数一样?write()
类同。
读写操作什么情况下会被阻塞?
- 读(read):读套接字是将套接字接收缓存区中数据读取到应用层中,如果此时接收缓存区中为空、没有待读取的数据,读操作将被阻塞;
- 写(write):同理,写套接字是将应用层中数据写到套接字发送缓存区中,如果此时发送缓存区中剩余空间大小为0、没有可写空间,写操作将被阻塞。
套接字设置为阻塞/非阻塞模式下,read()/write()表现差异
除上之外,read()
、write()
有一重要区别需要注意,阻塞模式下:
- 接收缓存区中有数据,
read()
将数据读取至应用层,即使缓存数据长度小于想要获取长度,read()
也在读取后返回; - 而
write()
将发送缓存区中剩余空间写完后,仍有待写入数据没有写完,它将继续等待直到将所有数据写入发送缓存区中。
嗯,read()
在努力,write()
在尽力。
实用的读/写函数
/**@brief: 从套接字读取n个字节数据 * @param[i]: const int sockFd, 套接字ID * @param[i]: const int n, 待读取字节数 * @param[o]: char *pBuf, 数据缓存区 * @return: 返回成功读取的字节数,失败返回-1 */ size_t readn(char *pBuf, const int sockFd, const size_t n) { size_t nLeft = n; // 剩余待读取的字节数 ssize_t nRead = 0; // 当前此读取的字节数 if (NULL == pBuf || sockFd < 0 || n <= 0) { CLIENT_MAIN_DEBUG(ERROR, "readn, param is invalid.\n"); return FAILURE; } while (nLeft > 0) { nRead = read(sockFd, pBuf, nLeft); if (nRead < 0) // 读取异常处理 { if (EINTR == errno) // 中断异常,重新读取 { CLIENT_MAIN_DEBUG(DEBUG, "read is interrupted by others.\n"); continue; } else { CLIENT_MAIN_DEBUG(ERROR, "read failed, %s.\n", strerror(errno)); return FAILURE; } } else if (0 == nRead) // 读取到文件结束符(FIN) { CLIENT_MAIN_DEBUG(DEBUG, "read the end of file.\n"); return (n - nLeft); } else { nLeft -= nRead; pBuf += nRead; } } return n; }
/**@brief: 向套接字写n个字节数据 * @param[i]: const int sockFd, 套接字ID * @param[i]: const int n, 待读取字节数 * @param[i]: const char *pBuf, 数据缓存区 * @return: 返回成功写入的字节数,失败返回-1 */ size_t writen(const int sockFd, const size_t n, const char *pBuf) { size_t nLeft = n; // 剩余待写入的字节数 ssize_t nWrite = 0; // 当前写入的字节数 if (sockFd < 0 || n <= 0 || NULL == pBuf) { CLIENT_MAIN_DEBUG(ERROR, "writen, param is invalid.\n"); return FAILURE; } while (nLeft > 0) { nWrite = write(sockFd, pBuf, nLeft); if (nWrite <= 0) // 写入异常处理 { if (EINTR == errno) // 中断异常,重新写入 { CLIENT_MAIN_DEBUG(DEBUG, "write is interrupted by others.\n"); continue; } else { CLIENT_MAIN_DEBUG(ERROR, "write failed, %s.\n", strerror(errno)); return FAILURE; } } else { nLeft -= nWrite; pBuf += nWrite; } } return n; }
为什么读写操作时,套接字一般被设置为阻塞模式、而不设置为非阻塞模式?
套接字为非阻塞模式时,读写操作被阻塞则直接返回,如果还想使read()
/write()
实际读写的数据与想要操作的数据相同,那么就需要更为复杂的异常处理逻辑。而对于单纯的读写套接字来说,非阻塞并没有带来其他的便利。综上来说,读写套接字时将其设置为非阻塞?大可不必!
这篇关于套接字的读写操作在阻塞、非阻塞模式下的表现的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-07如何利用看板工具优化品牌内容创作与审批,确保按时发布?
- 2025-01-07百万架构师第十一课:源码分析:Spring 源码分析:Spring源码分析前篇|JavaGuide
- 2025-01-07质量检测标准严苛,这 6 款办公软件达标了吗?
- 2025-01-07提升品牌活动管理的效率:看板工具助力品牌活动日历的可视化管理
- 2025-01-07宠物商场的精准营销秘籍:揭秘看板软件的力量
- 2025-01-07“30了,资深骑手” | 程序员能有什么好出路?
- 2025-01-07宠物公园的营销秘籍:看板软件如何帮你精准触达目标客户?
- 2025-01-07从任务分解到资源优化:甘特图工具全解析
- 2025-01-07企业升级必备指南:从传统办公软件到SaaS工具的转型攻略
- 2025-01-07一文告诉你IT项目管理如何做到高效