简体   繁体   English

通过同一个套接字发送和接收

[英]Send and receive over the same socket

I'm pretty new to Java sockets and I'm having problems using the same socket to send and receive data. 我是Java套接字的新手,我在使用相同的套接字发送和接收数据时遇到了问题。

The server is on an Android device: 服务器位于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");

The client runs on a Linux machine with Java 6: 客户端在带有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");

The problem here is that the server gets stuck while (dataInputStream.read() != -1); 这里的问题是服务器卡住了while (dataInputStream.read() != -1); line. 线。 Looks like the client never closes the sending. 看起来客户端永远不会关闭发送。

If I do dataOutputStream.close() in the client part (after writing, of course), then it does work but then the client dies on while (dataInputStream.read() != -1); 如果我在客户端部分中执行dataOutputStream.close() (当然,在编写之后),那么它确实有效,但随后客户端就会死掉while (dataInputStream.read() != -1); saying the socket has been closed. 说插座已关闭。

I want to keep the whole socket open for more data interchange over this same socket until a closing command is sent. 我希望保持整个套接字打开,以便在同一个套接字上进行更多数据交换,直到发送关闭命令。

I'm obviously doing something wrong here, any insights? 我在这里做错了什么,有什么见解吗? Thanks in advance! 提前致谢!

You neither close the socket nor the outputstream. 你既不关闭套接字也不关闭输出流。 You do a shutdownOutput() in the client side: 您在客户端执行shutdownOutput()

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

This is called a half close, since it closes only one direction and leaves the other direction open. 这称为半关闭,因为它只关闭一个方向并使另一个方向打开。

edit : Olaf showed a built-in way to realize the request-response scenario in the question. 编辑 :奥拉夫展示了一种内置的方式来实现问题中的请求 - 响应场景。

Closing a stream obtained from a socket also closes the socket ( see also ).On the other hand it is impossible for the InputStream obtained from a socket to see if all the data was sent as long as the stream/socket is open(there could be more bits on its way!). 关闭从套接字获取的流也会关闭套接字( 另请参阅 )。另一方面,只要流/套接字打开,从套接字获取的InputStream就不可能查看是否所有数据都已发送(可能在它的路上更多的位!)。 A 2-way communication can not work this way, unless using Olafs example. 除非使用Olafs示例,否则双向通信无法以这种方式工作。 That allows to wait for the server response. 这允许等待服务器响应。

What you can do is define an end-signal yourself (eg the string "END") and either side listens until that end signal is read, then writes. 您可以做的是自己定义一个结束信号(例如字符串“END”),并且任何一方都会监听,直到读取该结束信号,然后写入。 But that comes with all sorts of other problems you will encounter for sure (what if the sent text contains the end signal? what if the partner dies before sending end? timeouts?...). 但是这会带来你遇到的各种其他问题(如果发送的文本中包含结束信号怎么办?如果伙伴在发送结束之前死了怎么办?超时?...)。 see also 也可以看看

I would try and look at SOAP or RESTful services that are well supported in Java (but I don't know how well on Android). 我会尝试查看Java中支持的SOAP或RESTful服务(但我不知道在Android上有多好)。 Generally there are many libraries that tackle these problems for you and relieve you from the low level networking. 通常,有许多库可以帮助您解决这些问题,并使您免受低级网络的影响。 It almost always pays off to use an existing solution. 使用现有解决方案几乎总能带来回报。

尝试通过执行dataOutStream.flush()刷新OutputStream

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM