【问题标题】:C: Send nested Struct over TCP socketC:通过 TCP 套接字发送嵌套结构
【发布时间】:2017-04-24 23:32:48
【问题描述】:

虽然这可能是重复的帖子,但我想确定它在我的特定代码中是如何工作的。

我想实现什么?

通过 TCP/IP 连接发送和接收结构。

到目前为止我有什么?

发件人

初始化结构:

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;

我现在想向连接的 TCP 客户端发送一个 s_OUTDATA 结构。

分配内存(正确吗?):

s_OUTDATA *poutData = malloc(sizeof(s_OUTDATA));
poutData->sDATAout = malloc(sizeof(s_OUTPUTDATA));
poutData->sHeader = malloc(sizeof(s_HEADER));  

发送结构体(我怎样才能得到整个 s_OUTDATA 结构体的正确大小?):

if ((send(sendSocket, poutData, 1024, 0)) == -1) {
        fprintf(errlog, "%.3f error: %s(): Failure Sending Message!\n", gettime(), __func__);
        close(sendSocket);
    }

接收者

初始化结构:

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;

分配内存(正确吗?):

s_OUTDATA *p = malloc(sizeof(s_OUTDATA));
poutData->sDATAout = malloc(sizeof(s_OUTPUTDATA));
poutData->sHeader = malloc(sizeof(s_HEADER));  

接收结构体:

if ((num = recv(newSocket, p, 1024,0)) == -1) {
   perror("recv");
   exit(1);
}
else if (num == 0) {
   printf("Connection closed\n");
}

有什么问题?

在尝试处理接收到的数据时,我遇到分段错误

printf("ui_index: %d\n", p->sDATAout->ui_index);

我错过了什么?

我想我在内存分配上做错了什么,但我不确定是什么以及如何解决它。

【问题讨论】:

    标签: c sockets struct tcp malloc


    【解决方案1】:

    看看你发送的结构:

    typedef struct soutdata {
        s_HEADER *sHeader;
        s_OUTPUTDATA *sDATAout;
    } s_OUTDATA;
    

    这不包含s_HEADERs_OUTPUTDATA实例,而是指向这些结构的指针。所以你不是在发送数据,而是在发送指针。

    由于指针地址仅对创建它们的进程有意义,因此接收端的这些指针并不指向有效的内存位置,因此取消引用这些指针会导致 undefined behavior

    不包含指针,而是将结构更改为包含实际数据:

    typedef struct soutdata {
        s_HEADER sHeader;
        s_OUTPUTDATA sDATAout;
    } s_OUTDATA;
    

    然后你发送,给出结构的大小:

    send(sendSocket, p, sizeof(s_OUTDATA), 0)
    

    您需要解决的其他问题是 endianness结构填充

    一些系统以最低有效字节 (LSB) 首先存储整数类型,而其他系统则以最高有效字节 (MSB) 开头。 htonlhtons 函数可以分别将 32 位和 16 位值从主机字节顺序(LSB 或 MSB)转换为网络字节顺序 (MSB),ntohlntohs 执行相反的操作这两个函数。

    struct 可能在元素之间或末尾包含一定数量的填充。填充的布局方式取决于实现。因此,struct 在一个系统上的二进制布局可能与另一个系统上的不同。

    可以通过单独发送每个数据字段而不是整个结构来解决填充处理问题,以便发送的数据采用已知格式。或者,您可以使用this guide to structure packing 来构建您的结构,从而可能消除填充或在最后将其减少到已知数量。

    【讨论】:

    • 感谢您的快速回复。哇,完全错过了。但是现在我在使用两个结构的指针时遇到编译错误(因为它们不再存在)。我需要将所有内容都更改为实例吗?
    • @Frechdachs 是的,因为成员的数据类型已更改,您需要解决如何使用它们。 IE。 p->sHeader.i_head 而不是 p->sHeader->i_head
    • 好吧,该死的。因为我有一个函数,它带有一个指向 s_OUTPUTDATA 结构的指针作为返回,现在我需要返回整个结构,这太重了。或者我可以将指针内容转换为实例吗?
    • @Frechdachs 根据函数的使用方式,您可能仍然可以使用指针。不要返回一个,而是将一个作为参数(作为该类型变量的地址)传递给函数将填充的参数。
    猜你喜欢
    • 2016-01-11
    • 2018-06-26
    • 1970-01-01
    • 2014-09-02
    • 2016-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    相关资源
    最近更新 更多