您好我编写了linux守护程序,它以udp数据包的形式发送文件。
问题是在字符串"abc\0asdf"
中它只发送abc
非空字符和asdf
(空符号后的所有字符),
有udp客户端代码,它发送数据包:
int sock;
struct sockaddr_in server_addr;
struct hostent *host;
host= (struct hostent *) gethostbyname((char *)ip);
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
perror("socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
memset(server_addr.sin_zero,0,8);
和发送缓冲区的代码:
if (sendto(sock, buf, sizeof buf, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))==-1)
在服务器端我需要接收二进制缓冲区:
定义套接字代码:
int sock;
int addr_len, bytes_read;
struct sockaddr_in server_addr , client_addr;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = INADDR_ANY;
//bzero(&(server_addr.sin_zero),8);
memset(server_addr.sin_zero,0,8);
if (bind(sock,(struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1){
perror("Bind");
exit(1);
}
addr_len = sizeof(struct sockaddr);
diep("sendto()");
并接收缓冲区(大循环):
bytes_read = recvfrom(sock,buf,sizeof (buf),0,
(struct sockaddr *)&client_addr, &addr_len);
有谁知道为什么我没有收到完整的缓冲区?
答案 0 :(得分:2)
通过查看注释,错误很可能是您将接收到的缓冲区视为字符串。
如果要打印/输出缓冲区,则需要先将空字符转换为其他字符。
答案 1 :(得分:2)
您应该使用for循环打印接收的缓冲区而不是printf:
for (int i=0; i<bytes_read; i++)
printf("%c",buf[i]);
答案 2 :(得分:2)
这是不正确的(格式已更改,因此它适合我的屏幕):
if (sendto(sock,
buf,
sizeof buf,
0,
(struct sockaddr *)&server_addr,
sizeof(struct sockaddr))==-1)
您想要sizeof(server_addr)
作为长度。这将大于sizeof(struct sockaddr)
。
另外,从联机帮助页:
返回值 成功时,这些调用将返回发送的字符数。出错时,返回-1,并正确设置errno。
您没有考虑返回低于sizeof(buf)
的某个值的情况。不知道如何发生这种情况,但似乎有待处理。
我对整体方法的评论与@jgauffin所说的相似。 buf
只是字节。这只是'\0'
终止它们的C字符串的约定,而不是要求。通常,在使用二进制字节缓冲区时,您还会跟踪大小。你只是假设将使用所有sizeof(buf)
,这是没有意义的。 (建议:您的sendto
有效负载的一部分可能应包括后面消息的大小?)