[英]C sockets send/recv buffer type
我正在使用unix套接字,当我的缓冲区是char类型(即发送和接收字符串)时,我可以发送()和recv()数据。 我使用了Beej的套接字指南,所用的例子是发送/接收字符串。
现在我想在一条消息中发送/ recv不同类型的数据。
例如,在一条消息中,我想发送一个整数,一个字符串,一个double和一个float。 我该怎么做呢? 更具体地说,我的消息“缓冲区”应该是什么类型的?
send和recv的原型:
int recv (int socket, void *buffer, size_t size, int flags)
int send (int socket, void *buffer, size_t size, int flags)
我对C / C ++和指针没有太多经验,所以这可能是一个noob问题。
如果有人能指导我朝着正确的方向前进,我真的很感激。 谢谢
最好的方法是封装您想要在结构中传递的信息。 然后传递结构的地址和长度。 请注意, buffer
是一个void*
因此这允许您传递包含您的信息的结构的地址。
这是我用于工具等安全副本的struct
一小部分,
struct message
{
size_t total_len;
size_t filename_len;
char *filename;
size_t text_len;
char *text;
char *iv;
char *salt;
unsigned char *hmac;
};
然后在send_message()
序列化message
,然后write
socket
bool send_message(const struct message *msg, const char *ip, const char *port)
{
...
connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr));
// Serialize to file
serialize(msg, "temp");
// Transfer the file over the network
fp = fopen("temp", "rb");
while((n = fread(buffer, 1, MAX_BUF_LEN, fp)) != 0)
{
write(sockfd, buffer, n);
}
fclose(fp);
remove("temp");
close(sockfd);
}
正如@vitaut所建议的那样,您可以使用库进行serialize
,我已将其作为学习体验实现。
您需要序列化发送方的对象并在接收方反序列化 。 在C ++中有许多库,例如Boost Serialization,或者如果你想重新发明轮子,你可以随时自己动手。
除非您计划发送大量数据(许多千字节)并经常(每秒几个数据包),否则我建议您将数据转换为字符串(也称为“序列化数据”)并以此方式传递。 它有几个好处:
int
或float
或double
大小是什么 - 或者字段之间的填充是什么。 另一方面,发送二进制数据很复杂,因为您需要担心数据字段的各个大小及其内部表示(字节顺序,如何在二进制中重新表示double
,结构中数据字段的填充,不能通过指针等等)。 唯一的好处是二进制数据更紧凑。 但这只会影响你是否有很多千字节和/或每秒发送大量数据包。
那么,要回答问题(“我如何发送结构?”),你只需发送一个指向结构的指针。
struct foo
{
int a;
int b;
};
struct foo s;
s.a = 10;
s.b = 20;
send(socket,&s,sizeof(s),0);
它真的很容易。 现在,另一方必须是相同的(也就是说,系统A内存中的结构必须与系统B上的结构相匹配)。 更好的方法是使用更具体的类型和一些函数来正确排序数据:
#ifndef __GNUC__
# define __attribute__(x)
#endif
#ifdef __SunOS
# pragma pack(1)
#endif
struct foo
{
uint32_t a;
uint32_t b;
} __attribute__((packed));
#ifdef __SunOS
# pragma pack()
#endif
struct foo s
/* to send */
s.a = htonl(10);
s.b = htonl(20);
send(socket,&s,sizeof(s),0);
/* to receive */
recv(socket,&s,sizeof(s),0);
s.a = ntohl(s.a);
s.b = ntohl(s.b);
当你想“通过网络”“移植”发送二进制数据时,你可以看到它开始变得系统特定,这就是为什么人们要转换为文本,或者很可能使用已经编写的序列化库。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.