Although this might be a duplicate post, I wanted to make sure how it works in my specific code.
What I wanna achieve?
Sending and receiving a struct over TCP/IP connection.
What I have so far?
Sender
initialize structs:
typedef struct soutputdata {
unsigned long long ull_date;
unsigned int ui_ixl;
unsigned int ui_type;
unsigned int ui_index;
char c_values[64][2];
int i_valueid;
} s_OUTPUTDATA;
typedef struct sheader {
int i_head;
} s_HEADER;
typedef struct soutdata {
s_HEADER *sHeader;
s_OUTPUTDATA *sDATAout;
} s_OUTDATA;
I now want to send an s_OUTDATA struct to a connected TCP client.
allocate memory (is this correct?):
s_OUTDATA *poutData = malloc(sizeof(s_OUTDATA));
poutData->sDATAout = malloc(sizeof(s_OUTPUTDATA));
poutData->sHeader = malloc(sizeof(s_HEADER));
Sending the struct (how can i get the correct size of the whole s_OUTDATA struct?):
if ((send(sendSocket, poutData, 1024, 0)) == -1) {
fprintf(errlog, "%.3f error: %s(): Failure Sending Message!\n", gettime(), __func__);
close(sendSocket);
}
Receiver
initialize structs:
typedef struct soutputdata {
unsigned long long ull_date;
unsigned int ui_ixl;
unsigned int ui_type;
unsigned int ui_index;
char c_values[64][2];
int i_valueid;
} s_OUTPUTDATA;
typedef struct sheader {
int i_head;
} s_HEADER;
typedef struct soutdata {
s_HEADER *sHeader;
s_OUTPUTDATA *sDATAout;
} s_OUTDATA;
allocate memory (is this correct?):
s_OUTDATA *p = malloc(sizeof(s_OUTDATA));
poutData->sDATAout = malloc(sizeof(s_OUTPUTDATA));
poutData->sHeader = malloc(sizeof(s_HEADER));
Receiving the struct:
if ((num = recv(newSocket, p, 1024,0)) == -1) {
perror("recv");
exit(1);
}
else if (num == 0) {
printf("Connection closed\n");
}
What is the problem?
When trying to work with the received data I get a segmentation fault.
printf("ui_index: %d\n", p->sDATAout->ui_index);
What am I missing?
I presume I have done sth wrong with the memory allocation but I am not sure what and how to solve it.
答案 0 :(得分:1)
看看你发送的结构:
typedef struct soutdata {
s_HEADER *sHeader;
s_OUTPUTDATA *sDATAout;
} s_OUTDATA;
这不包含s_HEADER
和s_OUTPUTDATA
的实例,但指针包含这些结构。所以你不是发送数据,而是指针。
由于指针地址仅对创建它们的进程有意义,因此接收端的这些指针不指向有效的内存位置,因此取消引用这些指针会导致undefined behavior。
不是包含指针,而是更改结构以包含实际数据:
typedef struct soutdata {
s_HEADER sHeader;
s_OUTPUTDATA sDATAout;
} s_OUTDATA;
然后发送,给出结构的大小:
send(sendSocket, p, sizeof(s_OUTDATA), 0)
您需要解决的其他问题是 endianness 和结构填充。
某些系统首先存储具有最低有效字节(LSB)的整数类型,而其他系统首先以最高有效字节(MSB)开始。 htonl
和htons
函数可以分别将32位和16位值从主机字节顺序(LSB或MSB)转换为网络字节顺序(MSB),以及ntohl
和{ {1}}执行这两个函数的反向。
ntohs
可能在元素之间或末尾包含一些填充量。如何布局填充是依赖于实现的。因此,一个系统上struct
的二进制布局可能与另一个系统上的二进制布局不同。
处理填充可以通过分别发送每个数据字段而不是整个结构来解决,以便发送的数据采用已知格式。或者,您可以使用this guide to structure packing来构建结构,以便可能在最后消除填充或将其减少到已知量。