在同一个 UDP 数据包中发送 ASCII 字符和 int
Sending ASCII characters and int in the same UDP packet
我需要通过 UDP 套接字发送一个数据包,其中将有一个以 ASCII 字符串形式编写的六位数字,在换行符之后,相同的数字,但以字节为单位 int
,如下所示:31 32 33 34 35 36 0A 00 01 E2 40
对应于 123456\n(123456)
- 整数在括号中。到目前为止,我可以发送我的字符串和我的换行符,但是当涉及到 int
时,我得到 0 个字节被写入缓冲区并且我的 int
缓冲区数组中没有任何内容被发送。此外,如果我检查 int
缓冲区数组的文本内容,它有奇怪的“Fs”数量:00 01 FFFFFFE2 40
这是我的 UDP 客户端:
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
char buf[11];
int main(int argc, char **argv)
{
struct sockaddr_in adr;
int sock, r;
unsigned int port;
char abcd[512];
char intBuff[4];
unsigned int index = 123456;
unsigned int networkHost;
networkHost = htonl(index);
memcpy(intBuff, (char*)&networkHost,sizeof(uint32_t));
printf("Int buffer: ");
for(int i=0; i<sizeof(uint32_t); i++){
printf("%02X ", intBuff[i]); //Output is 00 01 FFFFFFE2 40
}
int x1 = sprintf(buf,"%s\n","123456");
printf("\n1st data write: %i\n", x1); //7 bytes are written
int x2 = sprintf(&buf[x1], "%s",intBuff);
printf("2nd data write: %i\n", x2); //0 bytes are written
//SERVER
printf("IP: ");
scanf("%s", abcd);
printf("PORT: ");
scanf("%u", &port);
sock = socket(AF_INET, SOCK_DGRAM, 0);
adr.sin_family = AF_INET;
adr.sin_port = htons(port);
adr.sin_addr.s_addr = inet_addr(abcd);
r = sendto(sock,
buf,
11,
0,
(struct sockaddr*) &adr,
sizeof(adr));
close(sock);
return 0;
}
问题
出现奇怪的值是因为你的char
数组是signed
,当你传递给printf
时,编译器将它解释为signed
整数。
不要使用sprintf(...,"%s", ...)
复制可能包含零字节的二进制数据,因为"%s"
格式在到达[=18=]
空字符时会突然停止复制。
解决方案
- 使用
unsigned char
,因此编译器在将数据传递给printf
时不会将其解释为signed
整数。
- 使用
memcpy
将intBuff
复制到buf
。
代码示例
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <arpa/inet.h>
int main() {
unsigned char buf[11];
unsigned char intBuff[sizeof(uint32_t)];
uint32_t index = 123456;
uint32_t networkHost;
networkHost = htonl(index);
memcpy(intBuff, &networkHost, sizeof(networkHost));
for (int i=0; i < sizeof(intBuff); i++){
printf("%02x ", intBuff[i]);
}
int x1 = sprintf(buf,"%s\n","123456");
printf("\n1st data write: %i\n", x1); // 7 bytes are written
// It is certain that the write is sizeof(intBuff) in size.
memcpy(&buf[x1], intBuff, sizeof(intBuff));
int total_len = x1 + sizeof(intBuff);
printf("Packed data: ");
for (int i = 0; i < total_len; i++) {
printf("%02x ", buf[i]);
}
putchar('\n');
}
输出
ammarfaizi2@integral:/tmp$ gcc x.c -o x
ammarfaizi2@integral:/tmp$ ./x
00 01 e2 40
1st data write: 7
Packed data: 31 32 33 34 35 36 0a 00 01 e2 40
ammarfaizi2@integral:/tmp$
表示整数的字节通常可以具有任何值,因为整数具有各种值。所以一个字节可能为零。然后使用 printf
和 %s
将这些字节写入缓冲区将在零字节处停止,因为 %s
需要一个字符串。字符串的定义是,它是一个以零字节结尾的字符序列。
对于您使用的值,第一个字节是零,因此 printf
立即停止,不写入任何字节。
不是使用printf
将字节复制到缓冲区,而是直接用memcpy
复制它们:
memcpy(&buf[x1], &networkHost, sizeof networkHost);
您根本不需要 intBuff
,可以将其从您的程序中删除。
我需要通过 UDP 套接字发送一个数据包,其中将有一个以 ASCII 字符串形式编写的六位数字,在换行符之后,相同的数字,但以字节为单位 int
,如下所示:31 32 33 34 35 36 0A 00 01 E2 40
对应于 123456\n(123456)
- 整数在括号中。到目前为止,我可以发送我的字符串和我的换行符,但是当涉及到 int
时,我得到 0 个字节被写入缓冲区并且我的 int
缓冲区数组中没有任何内容被发送。此外,如果我检查 int
缓冲区数组的文本内容,它有奇怪的“Fs”数量:00 01 FFFFFFE2 40
这是我的 UDP 客户端:
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
char buf[11];
int main(int argc, char **argv)
{
struct sockaddr_in adr;
int sock, r;
unsigned int port;
char abcd[512];
char intBuff[4];
unsigned int index = 123456;
unsigned int networkHost;
networkHost = htonl(index);
memcpy(intBuff, (char*)&networkHost,sizeof(uint32_t));
printf("Int buffer: ");
for(int i=0; i<sizeof(uint32_t); i++){
printf("%02X ", intBuff[i]); //Output is 00 01 FFFFFFE2 40
}
int x1 = sprintf(buf,"%s\n","123456");
printf("\n1st data write: %i\n", x1); //7 bytes are written
int x2 = sprintf(&buf[x1], "%s",intBuff);
printf("2nd data write: %i\n", x2); //0 bytes are written
//SERVER
printf("IP: ");
scanf("%s", abcd);
printf("PORT: ");
scanf("%u", &port);
sock = socket(AF_INET, SOCK_DGRAM, 0);
adr.sin_family = AF_INET;
adr.sin_port = htons(port);
adr.sin_addr.s_addr = inet_addr(abcd);
r = sendto(sock,
buf,
11,
0,
(struct sockaddr*) &adr,
sizeof(adr));
close(sock);
return 0;
}
问题
出现奇怪的值是因为你的char
数组是signed
,当你传递给printf
时,编译器将它解释为signed
整数。
不要使用sprintf(...,"%s", ...)
复制可能包含零字节的二进制数据,因为"%s"
格式在到达[=18=]
空字符时会突然停止复制。
解决方案
- 使用
unsigned char
,因此编译器在将数据传递给printf
时不会将其解释为signed
整数。 - 使用
memcpy
将intBuff
复制到buf
。
代码示例
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <arpa/inet.h>
int main() {
unsigned char buf[11];
unsigned char intBuff[sizeof(uint32_t)];
uint32_t index = 123456;
uint32_t networkHost;
networkHost = htonl(index);
memcpy(intBuff, &networkHost, sizeof(networkHost));
for (int i=0; i < sizeof(intBuff); i++){
printf("%02x ", intBuff[i]);
}
int x1 = sprintf(buf,"%s\n","123456");
printf("\n1st data write: %i\n", x1); // 7 bytes are written
// It is certain that the write is sizeof(intBuff) in size.
memcpy(&buf[x1], intBuff, sizeof(intBuff));
int total_len = x1 + sizeof(intBuff);
printf("Packed data: ");
for (int i = 0; i < total_len; i++) {
printf("%02x ", buf[i]);
}
putchar('\n');
}
输出
ammarfaizi2@integral:/tmp$ gcc x.c -o x
ammarfaizi2@integral:/tmp$ ./x
00 01 e2 40
1st data write: 7
Packed data: 31 32 33 34 35 36 0a 00 01 e2 40
ammarfaizi2@integral:/tmp$
表示整数的字节通常可以具有任何值,因为整数具有各种值。所以一个字节可能为零。然后使用 printf
和 %s
将这些字节写入缓冲区将在零字节处停止,因为 %s
需要一个字符串。字符串的定义是,它是一个以零字节结尾的字符序列。
对于您使用的值,第一个字节是零,因此 printf
立即停止,不写入任何字节。
不是使用printf
将字节复制到缓冲区,而是直接用memcpy
复制它们:
memcpy(&buf[x1], &networkHost, sizeof networkHost);
您根本不需要 intBuff
,可以将其从您的程序中删除。