C 使用protobuf序列化消息与zeromq通信
我无法使用C通过ZeroMQ套接字接收protobuf中序列化的消息。 我已经序列化了客户端输入的消息,并使用zhelpers.h中定义的s_send()函数将该缓冲区发送到服务器。服务器代码与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
#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指向的内容。否则,请针对新问题发布一个新问题,因为您的代码似乎已经发生了很大的变化。