Отправить структуру через сокет, используя TPL для сериализации, используя C - PullRequest
3 голосов
/ 24 июня 2009

Прочитав несколько связанных вопросов, я решил использовать библиотеку tpl для сериализации моих структур с целью отправки и получения их через сокеты. У меня проблемы с пониманием, как отправлять и получать изображения TPL с помощью сокетов. Я получаю сообщение об ошибке segfault на стороне сервера при вызове функции 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

Ответы [ 3 ]

3 голосов
/ 24 июня 2009

Похоже, вы неправильно используете tpl_dump, по крайней мере, на клиенте - второй аргумент должен быть void**, а не int*. Макрос сохраняет адрес выделенного буфера в целое число addr, поэтому вы отправляете на сервер адрес (плюс немного мусора), а не данные. Последовательность вызовов на стороне сервера также выглядит не по порядку.

Присмотревшись к вашему источнику:

  • удалить амперсанды (&) из buf и len; 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 голос
/ 10 октября 2013

Любой, кто просматривает эту тему, сообщение Эрика де Араужо от 16 июля 2009 года в 14:49 (его исправленный код) работает ТОЛЬКО ЕСЛИ вы исправили одну ошибку в его разделе «Код сервера»:

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

должно быть изменено на:

tn = tpl_map("S(ci)", &receive);
0 голосов
/ 16 июля 2009

Для каждого запроса, вот успешная реализация с использованием сокетов:

Код клиента:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...