如何在C语言中通过Socket发送包含指针的结构体?
问题:TCP Socket发送含指针的结构体导致段错误
你定义的结构体如下:
typedef struct email{ unsigned char * message; }mail;
尝试通过TCP Socket整体发送该结构体时,服务端出现段错误,客户端和服务端代码如下:
客户端代码
mail messageServer; printf("Choose message: "); scanf("%s",messageServer.message); printf("Message: %s\n", messageServer.message); send(fd, &messageServer, sizeof(struct email), 0);
服务端代码
mail messageServer; printf("Before recv\n"); recv(fd2, &messageServer, sizeof(struct email), 0); printf("After recv"); printf("Message: %s\n",messageServer.message);
问题原因
- 客户端内存未初始化:
messageServer.message是未初始化的野指针,直接用scanf写入会操作随机内存地址,大概率引发客户端崩溃或内存损坏。 - 指针无法跨进程传输:结构体中的
message指针存储的是客户端进程内的内存地址,发送结构体时仅会把这个地址值传给服务端。服务端与客户端的地址空间完全独立,收到的地址在服务端进程中是无效的(要么未分配,要么属于其他进程),访问该地址必然触发段错误。
解决方案
方案1:改用固定大小字符数组(最简单直接)
将结构体中的指针替换为固定长度的字符数组,让字符串内容成为结构体的一部分,发送整个结构体即可传输完整数据:
typedef struct email { unsigned char message[256]; // 根据需求设置足够大的长度 } mail;
客户端使用时注意限制输入长度,避免数组溢出:
scanf("%255s", messageServer.message); // %255s 确保输入不超过数组容量
方案2:手动序列化数据(适配可变长度字符串)
如果必须用指针处理可变长度字符串,需要手动序列化数据,分两步完成发送与接收:
- 先发送字符串的长度,再发送字符串内容;
- 服务端根据接收的长度分配内存,再读取字符串内容。
修改后的客户端代码
mail messageServer; // 先分配内存存储输入 messageServer.message = malloc(256); if (messageServer.message == NULL) { perror("malloc failed"); return 1; } printf("Choose message: "); scanf("%255s", messageServer.message); // 发送字符串长度 int len = strlen((char*)messageServer.message); send(fd, &len, sizeof(int), 0); // 发送字符串内容 send(fd, messageServer.message, len, 0); free(messageServer.message);
修改后的服务端代码
int len; // 先接收字符串长度 recv(fd2, &len, sizeof(int), 0); // 分配对应大小的内存 mail messageServer; messageServer.message = malloc(len + 1); // +1 用于存储字符串结束符 if (messageServer.message == NULL) { perror("malloc failed"); return 1; } // 接收字符串内容 recv(fd2, messageServer.message, len, 0); messageServer.message[len] = '\0'; // 手动添加字符串结束符 printf("Message: %s\n", (char*)messageServer.message); free(messageServer.message);
内容的提问来源于stack exchange,提问作者sendix
相关产品推荐
相关产品推荐

