【问题标题】:Java Out Of Band (called "urgent data") dataJava Out Of Band(称为“紧急数据”)数据
【发布时间】:2013-03-06 14:15:44
【问题描述】:

这是一些尝试使用 OOB(紧急)数据的基本代码。我的问题是,如果客户端使用 C 或 Java,则服务器部分的行为会有所不同。 请注意,您可能认为两个客户端都有些棘手,但如果我使用 C 服务器(为了更好地控制 OOB),那么无论我的服务器端 OOB 控制是什么,两个客户端的行为都完全相同。

首先是服务器(Java)部分:

Socket s = ss.accept();
s.shutdownOutput();
s.setOOBInline(true);
InputStream is = s.getInputStream();
for (;;) {
  byte []d = new byte[3];
  int l = is.read(d);
  if (l==-1) break;
  for (int i=0; i<l; i++) System.out.print((char)d[i]);
  System.out.println();
  Thread.sleep(2000);
}

然后是客户端(Java)部分:

Socket s = new Socket("localhost",61234);
s.shutdownInput();
OutputStream os = s.getOutputStream();
byte []n = new byte[10];
for (int i=0; i<n.length; i++) n[i] = (byte)('A'+i);
byte m = (byte)('0');   
os.write(n);
System.out.println("normal sent");
s.sendUrgentData(m);
System.out.println("OOB sent");
os.write('Z');
System.out.println("normal sent");

然后是备用客户端 (C) 部分:

s = socket(PF_INET,SOCK_STREAM,0);
bzero(&a,sizeof(a));
a.sin_family = AF_INET;
a.sin_port = htons(61234);
a.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(s,(struct sockaddr *)&a,sizeof(a));
shutdown(s,SHUT_RD);
char m = '0';
char *n = "ABCDEFGHIJ";

printf("normal sent %d\n",write(s,n,strlen(n)));
printf("OOB sent %d\n",send(s,&m,1,MSG_OOB));
printf("normal sent %d\n",write(s,"Z",1));

现在这是我得到的(第一个 C 客户端,然后是 Java 客户端):

Accepting connection
ABC
DEF
GHI
J
Z
Accepting connection
ABC
DEF
GHI
J
0Z

Java 服务器似乎无法看到 C 客户端发送的 OOB 数据。为什么0 似乎丢失了?它没有,因为服务器至少检测到流中的 oob 边界。

【问题讨论】:

  • Quote from wikipedia: “在计算机网络中,带外数据(在 TCP 中称为“紧急数据”)在应用程序看来——就像一个单独的数据流来自主数据流的数据。” - 亲爱的投票者,这不是一个紧急问题,而是关于紧急数据
  • 这不能回答我的问题。首先,您可能会注意到我设置了 OOBInline 标志,其次它适用于一个客户端,但不适用于另一个客户端。
  • 这不是答案。只是很多人对你的问题投了反对票,因为他们在标题中读到“紧急”......
  • 我很少抛出 +1 来否定虚假的反对票,但这实际上是一个结构良好的问题。我希望你能得到答案。
  • 关于你的 C 代码:i 的值是多少?如果未初始化,则服务器可能会收到一些不可见的字符。

标签: java c sockets out-of-band


【解决方案1】:

在所有 Sockets 实现中,带外数据的支持方式不同。就这么简单。

微软的建议在这里:

目前,对 RFC 793(引入该概念的地方)有两种相互冲突的解释。

Berkeley Software Distribution (BSD) 中 OOB 数据的实现不符合 RFC 1122 中指定的主机要求。

具体来说,BSD中的TCP紧急指针指向紧急数据字节之后的字节,符合RFC的TCP紧急指针指向紧急数据字节。因此,如果应用程序将紧急数据从与 BSD 兼容的实现发送到与 RFC 1122 兼容的实现,则接收方会读取错误的紧急数据字节(它将位于数据流中正确字节之后的字节作为紧急数据读取)字节)。

为尽量减少互操作性问题,建议应用程序编写者不要使用 OOB 数据,除非需要与现有服务进行互操作。敦促 Windows 套接字供应商记录其产品实现的 OOB 语义(BSD 或 RFC 1122)。

如果你正在编写一个新的协议并且需要带外数据,我建议你需要一个单独的连接来处理你的紧急数据,或者你需要在应用层进行多路复用。

因此,如果可以选择,我的建议是不要使用 OOB 数据。

【讨论】:

  • 为什么这被否决了?似乎是一个很好的观点,并且与 OP 的回答一致,即代码在不同平台/JVM 版本上的行为不同。
【解决方案2】:

好的,这似乎与 JVM 实现有关。 我在不同的操作系统和 JVM 上做了不同的测试。

在使用 JDK 1.6(Java 7 未测试)的不同 Linux 上一切正常。

但是我的 Mountain Lion 出了点问题,它的行为因 Java 版本而异。 似乎是一个与苹果实现相关的 JVM 错误。

【讨论】:

  • Apple Mac OS 基于 BSD Unix,根据我的回答。
猜你喜欢
  • 1970-01-01
  • 2020-06-23
  • 2017-03-07
  • 2011-12-11
  • 1970-01-01
  • 2023-04-05
  • 1970-01-01
  • 2020-03-19
  • 1970-01-01
相关资源
最近更新 更多