C 使用protobuf序列化消息与zeromq通信

C 使用protobuf序列化消息与zeromq通信,c,sockets,protocol-buffers,zeromq,C,Sockets,Protocol Buffers,Zeromq,我无法使用C通过ZeroMQ套接字接收protobuf中序列化的消息。 我已经序列化了客户端输入的消息,并使用zhelpers.h中定义的s_send()函数将该缓冲区发送到服务器。服务器代码与zeromq包捆绑的测试代码相同,作为示例 这是我的客户端: #include "amessage.pb-c.h" #include "zhelpers.h" int main (void) { AMessage msg = AMESSAGE__INIT; // AMessage vo

我无法使用C通过ZeroMQ套接字接收protobuf中序列化的消息。 我已经序列化了客户端输入的消息,并使用zhelpers.h中定义的s_send()函数将该缓冲区发送到服务器。服务器代码与zeromq包捆绑的测试代码相同,作为示例

这是我的客户端:

#include "amessage.pb-c.h"
#include "zhelpers.h"

int main (void)
{

    AMessage msg = AMESSAGE__INIT; // AMessage
    void *buf;                     // Buffer to store serialized data
    unsigned len;

    printf ("Connecting to server...\n");
    void *context = zmq_ctx_new ();
    void *requester = zmq_socket (context, ZMQ_REQ);

    char buffer[256] = "";

    printf("[client] :");
    scanf("%s", buffer );

    msg.csmsg = buffer;
    len = amessage__get_packed_size(&msg);        
    buf = malloc(len);

    printf("[client]: pack msg len : %d\n ", len);
    printf("Sent msg : %d\n", buf);

    amessage__pack(&msg,buf);

    s_send(requester, buf);

    zmq_close (requester);
    zmq_ctx_destroy (context);
    return 0;
}
和服务器端:

#include "zhelpers.h"
#include <pthread.h>
#include <stdlib.h>
#include "amessage.pb-c.h"

#define MAX_MSG_SIZE 256

static size_t read_buffer (unsigned max_length, unsigned char *out)
{
   size_t cur_len = 0, nread;
   uint8_t c;
   while ((nread=fread(out + cur_len, 1, max_length - cur_len, stdin)) != 0)
   {
       cur_len += nread;
       if (cur_len == max_length)
       {
           fprintf(stderr, "[server]: max message length exceeded\n");
           exit(1);
       }
   }
   return cur_len;
 }


 static void * worker_routine (void *context) 
 {

    AMessage *msg;

    uint8_t buf[MAX_MSG_SIZE];
   char buffer[256];

   //  Socket to talk to dispatcher
   void *receiver = zmq_socket (context, ZMQ_REP);
   zmq_connect (receiver, "inproc://workers");

   while (1) {

          uint8_t *string = s_recv (receiver);

       if(string == 0)
            printf("[server]: Error: In receiving msg.\n");
       else
       {

        size_t msg_len = read_buffer (MAX_MSG_SIZE, string);
        printf("[server]: client msg len is: %d.\n", msg_len);
        msg = amessage__unpack(NULL, msg_len, string);   
        if (msg == NULL)
        {
            fprintf(stderr, "[server]: error unpacking incoming message\n");
            exit(1);
        }
        printf ("[client]: %s \n", msg->csmsg);

    }
    amessage__free_unpacked(msg, NULL);
    free (string);
    //  Do some 'work'
    sleep (1);

   }
   zmq_close (receiver);
   return NULL;
}

  int main (void)
  {
   void *context = zmq_ctx_new ();
   void *clients = zmq_socket (context, ZMQ_ROUTER);
   zmq_bind (clients, "tcp://*:5555");

   void *workers = zmq_socket (context, ZMQ_DEALER);
   zmq_bind (workers, "inproc://workers");

   //  Launch pool of worker threads
   int thread_nbr;
   for (thread_nbr = 0; thread_nbr < 5; thread_nbr++) {
        pthread_t worker;
        pthread_create (&worker, NULL, worker_routine, context);
   }
    //  Connect work threads to client threads via a queue proxy
    zmq_proxy (clients, workers, NULL);

    zmq_close (clients);
    zmq_close (workers);

    zmq_ctx_destroy (context);
    return 0;
  }
#包括“zhelpers.h”
#包括
#包括
#包括“amessage.pb-c.h”
#定义最大消息大小256
静态大小读取缓冲区(无符号最大长度,无符号字符*输出)
{
大小当前长度=0,nread;
uint8_t c;
而((nread=fread(out+cur_len,1,max_length-cur_len,stdin))!=0)
{
cur_len+=nread;
if(cur_len==最大长度)
{
fprintf(stderr,“[server]:超出了最大消息长度\n”);
出口(1);
}
}
返回cur_len;
}
静态void*worker_例程(void*context)
{
A消息*msg;
uint8_t buf[最大尺寸];
字符缓冲区[256];
//与调度程序对话的套接字
void*receiver=zmq_套接字(上下文,zmq_REP);
zmq_连接(接收器,“inproc://workers");
而(1){
uint8_t*字符串=s_recv(接收器);
如果(字符串==0)
printf(“[server]:错误:在接收消息时。\n”);
其他的
{
size\u t msg\u len=读取缓冲区(最大msg\u大小,字符串);
printf(“[服务器]:客户端消息长度为:%d.\n”,消息长度);
msg=amessage\uu unpack(NULL,msg\u len,string);
如果(msg==NULL)
{
fprintf(stderr,“[server]:解包传入消息时出错\n”);
出口(1);
}
printf(“[客户端]:%s\n”,msg->csmsg);
}
未打包的消息(消息,空);
自由(弦);
//做一些“工作”
睡眠(1);
}
zmq_关闭(接收器);
返回NULL;
}
内部主(空)
{
void*context=zmq_ctx_new();
void*clients=zmq_套接字(上下文,zmq_路由器);
zmq_绑定(客户端,“tcp://*:5555”);
void*workers=zmq_插座(上下文,zmq_经销商);
zmq_绑定(工人)inproc://workers");
//启动工作线程池
内螺纹丁腈橡胶;
用于(螺纹编号=0;螺纹编号<5;螺纹编号++){
pthread_t worker;
pthread_create(辅助线程,NULL,辅助线程例程,上下文)(&worker);
}
//通过队列代理将工作线程连接到客户端线程
zmq_代理(客户端、工作者、空);
zmq_close(客户);
zmq_close(工人);
zmq_ctx_销毁(上下文);
返回0;
}
知道我做错了什么吗?

您正在使用
s_send()
,它需要一个C字符串作为参数,并调用
strlen()
来确定其大小。但是,协议缓冲区数据是二进制数据,并且可能在消息中的任何位置包含空字节


而是使用
zmq\u send()
并将消息的长度提供给
zmq\u msg\u init\u size()
函数

:谢谢你的回答。尽管如此,我还是在memcpy()的服务器端遇到了异常<代码>zmq_msg_recv(&msg,接收器,0);memcpy(rBuf、zmq_msg_数据(&msg)、zmq_msg_大小(&msg))但是zmq_msg_大小在两端相同。知道我在接收消息数据时做错了什么吗?什么异常?写入无效内存?检查rBuf指向的内容。否则,请针对新问题发布一个新问题,因为您的代码似乎已经发生了很大的变化。