我是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");
客户端在带有Java 6的Linux机器上运行:
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);
上死亡,说套接字已经关闭。
我希望保持整个套接字打开,以便在同一个套接字上进行更多的数据交换,直到发送一个关闭命令。
我显然在这里做错了什么,有什么见解吗?提前谢谢!
答案 0 :(得分:12)
既不关闭套接字也不关闭输出流。您在客户端执行shutdownOutput():
...
dataOutputStream.write(bufferOut);
System.out.println("Sent");
socket.shutdownOutput();
...
这称为半关闭,因为它仅关闭一个方向并使另一个方向保持打开状态。
答案 1 :(得分:2)
编辑:Olaf展示了一种内置方式来实现问题中的请求 - 响应方案。
关闭从套接字获取的流也会关闭套接字(see also)。另一方面,从套接字获取的InputStream无法查看是否所有数据都是在流/ /套接字是打开的(可能会有更多位!)。除非使用Olafs示例,否则双向通信无法以这种方式工作。这允许等待服务器响应。
你可以做的是自己定义一个结束信号(例如字符串“END”),并且任何一方听到直到读取该结束信号,然后写入。但是这会带来你遇到的各种其他问题(如果发送的文本中包含结束信号怎么办?如果伙伴在发送结束之前死了怎么办?超时?...)。 see also
我会尝试查看Java中支持的SOAP或RESTful服务(但我不知道在Android上有多好)。通常,有许多库可以帮助您解决这些问题,并使您免受低级网络的影响。使用现有解决方案几乎总能带来回报。
答案 2 :(得分:0)
尝试通过执行dataOutStream.flush()