2012-10-15 298 views
3

我很新的Java套接字和我有问题使用相同的套接字发送和接收数据。发送和接收通过相同的套接字

的服务器是在Android设备上:

ServerSocket listenSocket = null; 
    OutputStream dataOutStream = null; 
    Socket socket = null; 
    InputStream dataInputStream = null; 

    // Listen 
    System.out.println("Start listening"); 
    try { 
     listenSocket = new ServerSocket(4370); 
     socket = listenSocket.accept(); 
     System.out.println("Connection accepted"); 
     dataInputStream = socket.getInputStream(); 
     dataOutStream = socket.getOutputStream(); 
     while (dataInputStream.read() != -1); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     close(listenSocket, socket); 
     return; 
    } 

    // Answer 
    System.out.println("Answering..."); 
    byte[] answer = {(byte) 0x82, (byte) 0xf8, 0, 0}; 
    try { 
     dataOutStream.write(answer); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     close(listenSocket, socket); 
     return; 
    } 

    close(listenSocket, socket); 
    System.out.println("Finished"); 

客户端Linux机器上运行的Java 6:

Socket socket = new Socket("192.168.1.33", 4370); 
    OutputStream dataOutputStream = socket.getOutputStream(); 
    InputStream dataInputStream = socket.getInputStream(); 
    byte[] bufferOut = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
    dataOutputStream.write(bufferOut); 
    System.out.println("Sent"); 

    while (dataInputStream.read() != -1);  
    socket.close(); 
    System.out.println("Finished"); 

的这里的问题是,服务器被卡住while (dataInputStream.read() != -1);线。看起来客户端从不关闭发送。

如果我在客户端部分(当然写入后)做dataOutputStream.close(),那么它确实工作,但是然后客户端死于while (dataInputStream.read() != -1);,表示套接字已关闭。

我想保持整个套接字打开,通过这个套接字进行更多的数据交换,直到发送关闭命令。

我明显在这里做错了什么,有什么见解?提前致谢!

回答

2

编辑冲洗的OutputStream:奥拉夫呈内置的方式来实现问题的请求 - 响应方案。

关闭从套接字获得的流也会关闭套接字(see also)。另一方面,从套接字获取的InputStream不可能在发生流/套接字打开时查看是否发送了所有数据(有可能会有更多的比特!)。双向通信不能以这种方式工作,除非使用Olafs示例。这允许等待服务器响应。

你可以做的是自己定义一个结束信号(例如字符串“END”),并且任何一方都会监听,直到读取结束信号,然后写入。但是,这会带来各种其他问题(如果发送的文本包含结束信号,如果合作伙伴在发送结束之前死亡,超时会怎么样?)。 see also

我会尝试着看一下在Java中很好支持的SOAP或RESTful服务(但我不知道在Android上有多好)。通常有很多库为您解决这些问题,并帮助您从低级网络中解脱出来。使用现有的解决方案几乎总是值得的。

+0

如果可以预先确定消息的长度,则还可以发送前几个字节(例如4个字节)以指示要跟随的有效载荷的长度。 – sgp15

+0

感谢您的回答,但除TCP之外,我无法使用任何其他功能。这是通过TCP实现的一个协议。 – m0skit0

+0

从技术上说,SOAP和REST确实使用TCP ...(:但是使用包含以下数据长度的头文件作为@sgp15建议的也是一个可行的替代方案,可以简化错误处理。一般来说,如果要使用套接字连接,您必须以某种方式定义一个通信协议,该协议明确标记了交换消息的边界。 – Pyranja

0

尝试做dataOutStream.flush()

+0

已经尝试过,结果相同。 – m0skit0

+0

在客户端,我正在做'outStream.write(outPacket);'然后读取,但服务器没有正确接收数据包。写完后冲洗为我工作! – wrapperapps

11

您既不关闭套接字,也不关闭输出流。您在客户端做了shutdownOutput()

... 
dataOutputStream.write(bufferOut); 
System.out.println("Sent"); 
socket.shutdownOutput(); 
... 

这就是所谓的半封闭,因为它仅关闭一个方向并保持其他方向打开。

+0

如果调用dataOutputStream.close()会发生什么?它仍然是一个接近一半? – sgp15

+0

@ sgp15这已经出现在上面的问题中:“如果我执行dataOutputStream.close()...则客户端在while(dataInputStream.read()!= -1)时停止运行;说套接字已关闭 –

+0

正在搜索请参阅:[Java套接字问题半关闭](http://stackoverflow.com/questions/3626401/java-socket-problems-half-closing)和[关闭套接字的输入流也关闭套接字连接?](http://stackoverflow.com/questions/3956163/does-closing-the-inputstream-of-a-socket-also-close-the-socket-connection) –

相关问题