C++ Socket调用recv()始终返回0:两种传参写法的差异原因问询
第二种recv写法失效的根本原因
首先明确recv函数的第二个参数要求:需要传入一块可写的用户态内存的起始地址,函数会把从socket收到的数据写入这块内存中。
两种写法的核心差异在于传入的指针值完全不同:
- 第一种正确写法中,
char blockSize[4]定义了一块4字节长度的合法栈内存,数组名blockSize传入recv时会隐式转换为指向这块栈内存首地址的指针,recv可以正常写入数据。 - 第二种错误写法中,
size_t blockSize = 0是定义了一个值为0的整型变量,你直接写(char*)blockSize是把变量存储的数值0强制转换为指针类型,相当于给recv传入了地址为0的空指针(NULL)作为缓冲区。内存0地址属于操作系统保护的禁止用户态程序访问的非法地址,recv无法往这个地址写入任何数据。
关于你观测到recv始终返回0的补充说明:
正常情况下传入非法缓冲区地址recv应该返回-1,同时设置errno为EFAULT表示地址非法。你观测到返回0的原因通常是调用recv时socket连接已经被对端主动关闭,此时recv会优先返回0表示连接到达EOF,不会再做缓冲区地址的合法性校验。
注意:如果你是想把
size_t变量本身的内存空间作为接收缓冲区,正确的写法应该是添加取地址符:recv(socket, (char*)&blockSize, 4, 0),但这种写法存在平台兼容性风险:size_t的长度在32位系统为4字节、64位系统为8字节,固定接收4字节可能出现数据截断或栈内存越界。
内容的提问来源于stack exchange,提问作者editsons
相关产品推荐
相关产品推荐

