Java OutputStream仅在关闭时刷新数据

时间:2015-04-20 14:29:17

标签: java sockets outputstream

Socket socket = new Socket("192.168.178.47", 82);

OutputStream out = socket.getOutputStream();
out.write("{ \"phone\": \"23456789\" }".getBytes());
out.flush();

//服务器

InputStream in = client.getInputStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();

int i = 0;
while((i = in.read()) >= 0) {
    bOut.write(i);
}

String complete = new String(bOut.toByteArray(), "UTF-8");

我曾尝试通过OutputStream将数据发送到套接字,但数据没有刷新。如果我在末尾添加out.close();,那么它可以正常工作,但套接字已关闭,我无法接受响应。有人知道为什么吗?服务器没有给出任何类型的错误。我曾经使用过Java 1.7!

6 个答案:

答案 0 :(得分:7)

服务器可能正在等待行尾。如果是这种情况,请在文本中添加“\ n”

答案 1 :(得分:3)

我不确定你问题中的“// Server”标签,但我假设以下代码是服务器代码:

InputStream in = client.getInputStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();

int i = 0;
while((i = in.read()) >= 0) {
    bOut.write(i);
}

String complete = new String(bOut.toByteArray(), "UTF-8");

这将继续读取,每次都阻塞,直到它从read()得到的值小于零。只有在流关闭时才会发生这种情况。

看起来你需要建立自己的协议。因此,不是寻找“< = 0”而是寻找一些表示消息结束的常量值。

这是我的意思的快速演示(我昨天没有时间)。我有3个班级,MessageMyClient(也是main班级)和MyServer。请注意,发送或接收换行没有任何意义。什么都没有设置tcpNoDelay。但它运作正常。其他一些说明:

  • 此代码仅发送和接收单个请求和响应。
  • 它不支持发送多个Message实例。这需要检查Message以及结束的开始。

Message上课:

public class Message {
    public static final String MSG_START = "<message>";
    public static final String MSG_END = "</message>";

    private final String content;

    public Message(String string){
        content = string;
    }

    @Override
    public String toString(){
        return MSG_START + content + MSG_END;
    }
}

MyServer上课

public class MyServer implements Runnable{
    public static final int PORT = 55555;

    @Override
    public void run(){
        try {
            ServerSocket serverSocket = new ServerSocket(PORT);
            Socket socket = serverSocket.accept();
            String message = getMessage(socket);
            System.out.println("Server got the message:  " + message);
            sendResponse(socket);
        }catch (IOException e){
            throw new IllegalStateException(e);
        }
    }

    private void sendResponse(Socket socket) throws IOException{
        Message message = new Message("Ack");
        System.out.println("Server now sending a response to the client: " + message);
        OutputStream out = socket.getOutputStream();
        out.write(message.toString().getBytes("UTF-8"));
    }

    private String getMessage(Socket socket) throws IOException{

        BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
        StringBuilder sb = new StringBuilder(100);
        byte[] bytes = new byte[1024<<8];
        while(sb.lastIndexOf(Message.MSG_END) == -1){
            int bytesRead = in.read(bytes);
            sb.append(new String(bytes,0,bytesRead,"UTF-8"));
        }

        return sb.toString();
    }
}

MyClient上课

public class MyClient {

    public static void main(String[] args){
        MyClient client = new MyClient();

        Thread server = new Thread(new MyServer());
        server.start();

        client.performCall();
    }

    public void performCall(){
        try {
            Socket socket = new Socket("127.0.0.1",MyServer.PORT);
            sendMessage(socket, "Why hello there!");
            System.out.println("Client got a response from the server: " + getResponse(socket));
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    public String getResponse(Socket socket) throws IOException{
        String response;

        StringBuilder sb = new StringBuilder(100);
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        while(sb.lastIndexOf(Message.MSG_END) == -1){
            int bytesRead = in.read(bytes);
            sb.append(new String(bytes,0,bytesRead,"UTF-8"));
        }
        response = sb.toString();

        return response;
    }

    public void sendMessage(Socket socket, String message) throws IOException{
        Message msg = new Message(message);
        System.out.println("Client now sending message to server: " + msg);
        OutputStream out = socket.getOutputStream();
        out.write(msg.toString().getBytes("UTF-8"));
    }
}

输出

Client now sending message to server: Why hello there!
Server got the message:  Why hello there!
Server now sending a response to the client: Ack
Client got a response from the server: Ack

Process finished with exit code 0

答案 2 :(得分:1)

尝试使用

socket.setTcpNoDelay(true);

出于性能原因发生缓冲(阅读Nagle的算法)。

答案 3 :(得分:0)

查看您的代码似乎没问题。然而,你发送的数量少于MTU Nagle的algothrim可能会将其保留,直到有足够的数据存在完整数据包或关闭套接字。

所以 - 试试这个:

socket.setTCPNoDelay(true);

http://en.wikipedia.org/wiki/Nagle%27s_algorithm https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#setTcpNoDelay-boolean-

答案 4 :(得分:0)

这是服务器问题,因为flush总是强制写入。测试它尝试运行此代码:

public static void main(String[] args) throws IOException, InterruptedException {
    Socket socket = new Socket("localhost", 8222);
    OutputStream out = socket.getOutputStream();
    for (int i = 0; i < 10; i++) {
        out.write((i + " : { \"phone\": \"23456789\" }").getBytes());
        out.flush();
        TimeUnit.SECONDS.sleep(1);
    }
}

之前,在shell上运行此命令:

$ nc -l localhost 8222

在端口8222上侦听数据。您将看到每{1}}输出

上显示每1秒数据

答案 5 :(得分:0)

问题不在于您没有正确刷新,而是在处理数据之前,读取代码等待套接字断开连接:

while((i = in.read()) >= 0)

只要可以从in(套接字的InputStream)读取内容,就会循环。在另一个对等设备断开连接之前,该条件不会失败。