Java Out Of Band(称为“紧急数据”)数据

时间:2013-03-06 14:15:44

标签: java c sockets out-of-band

以下是尝试使用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-client端发送的OOB数据。为什么0似乎丢失了?它没有,因为服务器至少检测到流中的oob边界。

2 个答案:

答案 0 :(得分:5)

在所有套接字实现上,不支持带外数据。就这么简单。

微软的建议在这里:

  

目前,RFC 793(引入概念的地方)存在两种相互矛盾的解释。

     

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

     

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

     

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

如果您正在编写新协议并需要带外数据,我建议您需要为紧急数据单独连接,或者需要在应用层复用它。

因此,我建议如果您有选择,不要使用OOB数据。

答案 1 :(得分:1)

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

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

但我的Mountain Lion出了问题,根据Java版本,它的行为有所不同。 似乎是与Apple实施相关的JVM错误。