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

时间:2009-06-24 15:19:19

标签: c sockets serialization

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

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

这不是我最终想要来回发送的结构,但我希望能够将这个样本弄清楚,以便将来能够做到这一点。我知道我在输入缓冲区和tpl_dump之间处理不当。我还在学习C(我以前的问题证明了这一点),所以如果我的代码中出现明显的错误,我会道歉。

编辑 尼古拉指出的问题已在下面的代码中得到纠正。但是,服务器代码会在error: tpl_load to non-root node

处记录tpl_unpack(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);

服务器代码:

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);

如果这会派上用场 - tpl user's guide

3 个答案:

答案 0 :(得分:3)

看起来你滥用tpl_dump,至少在客户端上 - 第二个参数应该是void**,而不是int*。宏将分配的缓冲区的地址存储到addr整数中,因此您要向服务器发送地址(加上一些垃圾),而不是数据。服务器端的呼叫顺序也看起来不正常。

仔细观察你的来源:

  • buflen中移除&符号(&amp;); tpl_load期望void*size_t;
  • 完成后你需要free()记忆;
  • 你需要注意简短的套接字读取 - 你可能会得到更少(或更多)然后你从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;
}

答案 1 :(得分:1)

任何看过这个帖子的人,Eric de Araujo在2009年7月16日14:49发布的帖子(他的更正代码)只有在你的服务器代码部分纠正了一个错误时才能正常工作:

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

必须更改为:

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

答案 2 :(得分: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);

服务器代码:

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);