Node.js服务器socket.write()与C客户端recv()通信卡住,求无需socket.end()的方案
C客户端与Node.js服务器Socket通信问题
现象描述
当Node.js服务器执行:
socket.write(Buffer.from("123"));
C客户端执行recv(socket_fd, buffer, 3, 0);时,连接会卡住。但如果服务器执行:
socket.end(Buffer.from("123"));
客户端就能正常接收数据,但该操作会关闭客户端的读socket,后续要接收数据必须重新创建连接。
核心疑问
有没有办法使用socket.write(Buffer.from("something"))发送数据,让客户端正常接收,同时无需调用socket.end();?
客户端接收代码
char *GetData(int socket_fd) { char init[] = {0x17, 0x22}; int bytes_read, n_reads = 0; char *buffer = (char *)malloc(BUFFER_SIZE); if (buffer == NULL) { puts("failed\n"); exit(EXIT_FAILURE); } send(socket_fd, init, 2, 0); int offset = 0; while ((bytes_read = recv(socket_fd, buffer + offset, BUFFER_SIZE, 0)) > 0) { if (bytes_read == -1) { puts("recv failed\n"); exit(EXIT_FAILURE); } offset += bytes_read; char *tmp = realloc(buffer, offset + BUFFER_SIZE); if (tmp == NULL) { puts("realloc failed\n"); exit(EXIT_FAILURE); } buffer = tmp; } return buffer; }
问题原因与解决方案
原因分析
客户端GetData函数中用了无限循环调用recv,只有当服务器调用socket.end()关闭连接时,recv才会返回0,循环才会终止。而服务器用socket.write()仅发送数据、不关闭连接时,客户端的recv会一直阻塞等待更多数据,表现为“卡住”。
解决办法
TCP是流协议,本身没有“消息边界”,必须自定义消息规则让客户端知道何时停止接收:
固定消息长度:服务器先发送4字节的整数表示数据长度,再发送实际数据;客户端先读取长度,再根据长度接收对应字节后停止。
服务器示例代码:const data = Buffer.from("123"); const lengthBuf = Buffer.alloc(4); lengthBuf.writeUInt32BE(data.length, 0); socket.write(lengthBuf); socket.write(data);特殊分隔符:在每条消息末尾添加约定好的分隔符(如
\n或自定义字节序列);客户端接收数据后检查是否包含分隔符,找到则停止接收,提取分隔符前的内容作为完整消息。固定单次接收字节数:若场景中每次发送数据长度固定(如3字节),客户端可直接接收指定长度后停止,无需循环。修改客户端接收逻辑:
bytes_read = recv(socket_fd, buffer + offset, 3, 0); if (bytes_read > 0) { offset += bytes_read; }
内容的提问来源于stack exchange,提问作者v.doro2
相关产品推荐
相关产品推荐

