使用tpl通过套接字发送结构,以便使用c进行序列化

使用tpl通过套接字发送结构,以便使用c进行序列化,c,sockets,serialization,C,Sockets,Serialization,在阅读了一些相关的问题之后,我决定使用来序列化我的结构,以便通过套接字发送和接收它们。我无法理解如何使用套接字发送和接收tpl映像。调用tpl\u dump函数时,服务器端出现segfault错误 我知道套接字在两端都工作,因为我以前使用代码来回发送字符串。我还能够使用tpl在客户端上创建和读取tpl映像,没有任何问题 这并不是我最终想要来回发送的结构,但我希望能够弄清楚这个示例,以便将来可以这样做。我知道我在传入缓冲区和tpl\u转储之间处理不当。我仍在学习C语言(我前面的问题证明了这一点),

在阅读了一些相关的问题之后,我决定使用来序列化我的结构,以便通过套接字发送和接收它们。我无法理解如何使用套接字发送和接收tpl映像。调用
tpl\u dump
函数时,服务器端出现segfault错误

我知道套接字在两端都工作,因为我以前使用代码来回发送字符串。我还能够使用tpl在客户端上创建和读取tpl映像,没有任何问题

这并不是我最终想要来回发送的结构,但我希望能够弄清楚这个示例,以便将来可以这样做。我知道我在传入缓冲区和
tpl\u转储之间处理不当。我仍在学习C语言(我前面的问题证明了这一点),所以如果我的代码中有明显的错误,我很抱歉

编辑 尼古拉指出的问题已在下面的代码中更正。但是,服务器代码记录
错误:tpl_加载到非根节点
,并且仍然在
tpl_解包(tn,0)处出现故障

客户端代码:

tpl_node *tn;

void *addr;
size_t len;

struct ci {
        char c;
        int i;
};
struct ci sample = {'a', 1};
tn = tpl_map("S(ci)", &sample); /* pass structure address */
tpl_pack(tn, 0);
tpl_dump(tn, TPL_MEM, &addr, &len );
tpl_free(tn);

send(sockfd, addr, len, 0);
tpl_node *tn;

    void *addr;
    size_t len;

    struct ci {
            char c;
            int i;
    };

    struct ci sample = {'a', 1};
    tn = tpl_map("S(ci)", &sample); /* pass structure address */
    tpl_pack(tn, 0);
    tpl_dump(tn, TPL_MEM, &addr, &len );
    tpl_free(tn);

    send(sockfd, addr, len, 0);
服务器代码:

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {

//error handling

} else {
    tpl_node *tn;

    struct ci {
        char c;
        int i;
};

struct ci recieve;

tpl_map("S(ci)", &recieve);
tpl_load(tn, TPL_MEM, &buf, &nbytes );
tpl_unpack(tn, 0);
tpl_free(tn);
char buf[256]; // buffer for client data
int nbytes;

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {

//error handling

} else {
    tpl_node *tn;

    struct ci {
        char c;
        int i;
    };

struct ci receive;

tpl_map("S(ci)", &receive);
tpl_load(tn, TPL_MEM, buf, nbytes );
tpl_unpack(tn, 0);
tpl_free(tn);

printf("Struct: {%c,%d}\n", receive.c, receive.i);

如果((nbytes=recv(i,buf,sizeof buf,0))看起来您至少在客户端上误用了
tpl_dump
,那么第二个参数应该是
void**
,而不是
int*
。宏将分配的缓冲区的地址存储到
addr
整数中,因此您正在发送地址(加上一些垃圾),而不是发送到服务器的数据。服务器端的调用顺序看起来也有问题。

仔细查看您的来源:

  • buf
    len
    中移除符号(&);
    tpl\u负载
    需要
    void*
    size\u t
  • 完成后,您需要
    释放()
    内存;
  • 您需要注意短套接字读取-您可能会收到比通过TCP套接字读取发送的更少(或更多)的消息。
下面是一个没有套接字的简单完整示例:


#include <stdlib.h>
#include <stdio.h>
#include "tpl.h"

int main( int argc, char* argv[] )
{
    char* buffer;
    size_t i, len;
    tpl_node *tn;
    struct ci { char c; int i; } s = {'a', 1}, s1;

    printf( "input {%c,%d}\n", s.c, s.i );

    tn = tpl_map( "S(ci)", &s );  /* pass structure address */
    tpl_pack( tn, 0 );
    tpl_dump( tn, TPL_MEM, &buffer, &len );
    tpl_free( tn );

    printf( "size = %lu\n", len );

    tn = tpl_map( "S(ci)", &s1 );
    tpl_load( tn, TPL_MEM, buffer, len );
    tpl_unpack( tn, 0 );
    tpl_free( tn );
    free( buffer );

    printf( "output {%c,%d}\n", s1.c, s1.i );
    return 0;
}

#包括
#包括
#包括“tpl.h”
int main(int argc,char*argv[])
{
字符*缓冲区;
尺寸i,len;
tpl_节点*tn;
结构ci{char c;int i;}s={'a',1},s1;
printf(“输入{%c,%d}\n”,s.c,s.i);
tn=tpl_映射(“S(ci)”,&S);/*传递结构地址*/
第三方物流包装(tn,0);
tpl_转储(tn、tpl_内存、缓冲区和len);
无第三方物流(tn);
printf(“大小=%lu\n”,len);
tn=tpl_图(“S(ci)”、&s1);
tpl_负载(总氮、tpl_膜、缓冲器、透镜);
tpl_开箱(tn,0);
无第三方物流(tn);
自由(缓冲);
printf(“输出{%c,%d}\n”,s1.c,s1.i);
返回0;
}

对于每个请求,下面是一个使用套接字的成功实现:

客户端代码:

tpl_node *tn;

void *addr;
size_t len;

struct ci {
        char c;
        int i;
};
struct ci sample = {'a', 1};
tn = tpl_map("S(ci)", &sample); /* pass structure address */
tpl_pack(tn, 0);
tpl_dump(tn, TPL_MEM, &addr, &len );
tpl_free(tn);

send(sockfd, addr, len, 0);
tpl_node *tn;

    void *addr;
    size_t len;

    struct ci {
            char c;
            int i;
    };

    struct ci sample = {'a', 1};
    tn = tpl_map("S(ci)", &sample); /* pass structure address */
    tpl_pack(tn, 0);
    tpl_dump(tn, TPL_MEM, &addr, &len );
    tpl_free(tn);

    send(sockfd, addr, len, 0);
服务器代码:

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {

//error handling

} else {
    tpl_node *tn;

    struct ci {
        char c;
        int i;
};

struct ci recieve;

tpl_map("S(ci)", &recieve);
tpl_load(tn, TPL_MEM, &buf, &nbytes );
tpl_unpack(tn, 0);
tpl_free(tn);
char buf[256]; // buffer for client data
int nbytes;

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {

//error handling

} else {
    tpl_node *tn;

    struct ci {
        char c;
        int i;
    };

struct ci receive;

tpl_map("S(ci)", &receive);
tpl_load(tn, TPL_MEM, buf, nbytes );
tpl_unpack(tn, 0);
tpl_free(tn);

printf("Struct: {%c,%d}\n", receive.c, receive.i);
char buf[256];//客户端数据缓冲区
整数字节;

如果((nbytes=recv(i,buf,sizeof buf,0))有人查看此线程,Eric de Araujo 2009年7月16日14:49的帖子(他的更正代码)只有在您更正其服务器代码部分中的一个错误时才有效:

tpl_map("S(ci)", &receive);
必须更改为:

tn = tpl_map("S(ci)", &receive);

感谢您指出服务器上的调用出现故障。我将客户端的代码从“int addr”更改为“void*addr”这是正确的吗?是的,它仍然存在故障。问题已经用我最近的代码和错误更新。这解决了正确处理tpl方面的问题。在我纠正了缓冲区和套接字的处理后,我能够成功地通过结构。