【问题标题】:Send a structure through a socket using tpl for serialization using c使用 tpl 通过套接字发送结构以使用 c 进行序列化
【发布时间】:2009-06-24 15:19:19
【问题描述】:

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

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

这不是我最终想要来回发送的结构,但我希望弄清楚这个示例,以便将来可以这样做。我知道我在传入缓冲区和tpl_dump 之间处理了一些错误。我仍在学习 C(正如我之前的问题所证明的那样),所以如果我的代码中有明显的错误,我深表歉意。

修改 Nikolai 指出的问题已在下面的代码中得到纠正。但是服务器代码记录 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

【问题讨论】:

    标签: c sockets serialization


    【解决方案1】:

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

    仔细查看您的来源:

    • buflen 中删除& 符号; 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;
    }
    

    【讨论】:

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

    任何查看此线程的人,Eric de Araujo 从 2009 年 7 月 16 日 14:49 发布的帖子(他更正的代码)只有在您更正他的服务器代码部分中的一个错误时才有效:

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

    必须改为:

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

    【讨论】:

      【解决方案3】:

      根据请求,这是使用套接字的成功实现:

      客户代码:

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

      【讨论】:

        猜你喜欢
        • 2011-06-18
        • 1970-01-01
        • 2016-04-04
        • 1970-01-01
        • 2016-06-06
        • 1970-01-01
        • 1970-01-01
        • 2016-01-11
        • 1970-01-01
        相关资源
        最近更新 更多