【问题标题】:Why is extra data being written to my output stream and how can I stop this?为什么额外的数据被写入我的输出流,我该如何阻止它?
【发布时间】: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/…

标签: java c sockets


【解决方案1】:

我的代码的问题在于 cmets 中正确指出的这一行

bytes_received = recv(connected,ptr1,10,0);

我错误地试图读取​​超过 4 个字节,这是转换为整数值所需的确切数字。

或者,要读取 4 个且仅 4 个字节,这可以写为

bytes_received = recv(connected, ptr1, 4, 0|MSG_WAITALL);

在 java 方面,正如 cmets 中所指出的,函数 write(int) 仅发送 1 个字节。

要发送多个字节,必须先将整数转换为 4 字节数组,然后数组中的每个字节都必须像这样发送

outToClient.write(rlen_array, 0, 4);

【讨论】:

    猜你喜欢
    • 2014-05-21
    • 1970-01-01
    • 2021-03-12
    • 2011-06-21
    • 2014-07-21
    • 2012-09-29
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    相关资源
    最近更新 更多