【发布时间】:2016-09-13 08:11:08
【问题描述】:
我正在尝试在我的 Java 服务器(它发送信息)和我的 C 客户端(它接收信息)之间建立一个简单的连接。
我想发送一个表示数组大小的整数,然后发送一个字节数组本身。我的java代码是这样的
Socket sc = new Socket("52.187.54.73", 19000);
while(true)
{
System.out.println("Socket open");
DataOutputStream outToClient = new DataOutputStream(sc.getOutputStream());
Random rand = new Random();
int rlen = rand.nextInt(10)%10 + 1;
byte[] a = new byte[rlen];
System.out.println("Size of the array is " + rlen);
for(int i = 0; i < rlen; i++)
a[i] = (byte)rand.nextInt(100);
outToClient.write(rlen);
outToClient.write(a,0,rlen);
//close socket
sc.close();
System.out.println("Done!");
//Break once done
break;
}
我的 C 代码看起来像这样
ptr1 = (void *)calloc(1, sizeof(int));
while(1){
sin_size = sizeof(client_addr);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
printf("\n Got a connection from (%s ,%d)",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
bytes_received = recv(connected,ptr1,10,0);
if(bytes_received<0){
printf("Something went wrong %s\n", strerror(errno));
}
printf("Bytes received: %d \n", bytes_received);
for(int i =0; i<bytes_received; i++){
unsigned char a = *(unsigned char *)(ptr1 + i*sizeof(unsigned char));
printf("Inc: %d", a);
}
假设上面的代码块有效并且我能够得到rlen的值,那么处理数组的代码如下:
ptr2 = calloc(rlen, sizeof(unsigned char));
bytes_received = recv(connected, ptr2, 1,0);// incoming, 0);
printf("bytes received: %d\n", bytes_received);
for(int i = 0; i < rlen; i++){
printf(" i = %d, val = %d\n ", i,*(unsigned char *)(ptr2 + i*sizeof(unsigned char)));
}
现在 Java 服务器发送一个介于 1 和 10 之间的数字。我之前尝试读取使用 int incoming = *(int *)ptr1; 发送的数字,但由于某种原因,有时我会得到像 51020210 这样的巨大值。
为了检查为什么会发生这种情况并进行调试,我编写了代码块:
for(int i =0; i<bytes_received; i++){
unsigned char a = *(unsigned char *)(ptr1 + i*sizeof(unsigned char));
printf("Inc: %d", a);
}
事实证明,有时发送的整数会变得非常大。
为什么会这样?在服务器端打印出rlen 向我展示了正确的值,但不确定的是我在客户端得到随机的非常大的值。
请注意,我在客户端收到的任何数字都有第一个数字作为rlen 的值。
例如,如果rlen 是6,那么随机非常大的值类似于689932423
稍后rlen 的值将变得非常大,大约为 1000 秒,所以我需要解决这个问题,不能简单地从客户端获取任何内容的第一个字节。
【问题讨论】:
-
sizeof(unsigned char)始终为 1。 -
Java 的
DataOutputStream.write(int)将 单字节 写入底层输出流。然后,您继续向 ptr1 指向的缓冲区读取 10 个字节(您尚未在最小、完整且可验证的示例中定义),然后将指针转换为指向 int 的指针并取消引用它。这(可能)破坏了别名 - 未定义的行为 - 并尝试从缓冲区中读取太多字节,更不用说可能的字节顺序问题了。 -
如果您希望其他人阅读您的代码,请缩进。
-
ptr1 = (void *)calloc(1, sizeof(int)); ... recv(connected,ptr1,10,0);你分配 4 个字节,然后让recv读取 10 个字节。只是一个例子。 -
memcpy是安全的成语。 stackoverflow.com/questions/544928/…