Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java BufferedWriter/PrintWriter/OutputStreamWriter don';t在调用.close()之前刷新缓冲区(通过套接字输出流)_Java_Sockets_Inputstream_Outputstream_Flush - Fatal编程技术网

Java BufferedWriter/PrintWriter/OutputStreamWriter don';t在调用.close()之前刷新缓冲区(通过套接字输出流)

Java BufferedWriter/PrintWriter/OutputStreamWriter don';t在调用.close()之前刷新缓冲区(通过套接字输出流),java,sockets,inputstream,outputstream,flush,Java,Sockets,Inputstream,Outputstream,Flush,每当我对标题中的任何写入程序(正在包装OutputStreamWriter)调用.flush(),刷新的数据都不会被发送;但是,在writer上调用.close()时,它会刷新,服务器可以读取数据。我不知道我是否调用了.write()或.readLine()错误,或者由于读取操作已被阻止,这就是问题所在?我需要找到一种在不关闭套接字的情况下刷新数据的方法(我将在另一个程序中使用它)。在我拥有的两个SSCCE中,都有用于调试的System.out.println()。在客户机中,它将转到“chec

每当我对标题中的任何写入程序(正在包装OutputStreamWriter)调用
.flush()
,刷新的数据都不会被发送;但是,在writer上调用
.close()
时,它会刷新,服务器可以读取数据。我不知道我是否调用了
.write()
.readLine()
错误,或者由于读取操作已被阻止,这就是问题所在?我需要找到一种在不关闭套接字的情况下刷新数据的方法(我将在另一个程序中使用它)。在我拥有的两个SSCCE中,都有用于调试的
System.out.println()
。在客户机中,它将转到“check4”并不执行任何循环(它在实际程序中执行更多的读写操作,只是在示例中无法将其关闭)。在服务器中,它进入“check2”并在
reader.readLine()
处阻塞。我已经读了很多书,但是我想到的是
readLine()
对于网络程序不是一个好主意,我应该实现自己的协议;然而,没有一篇文章指向一个好的教程网站,或者任何其他有好的网络编码教程的网站。以下是SSCCE:

客户SSCCE

package testClient;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;

public class Client {

    public static void main(String[] args) {
        try {
            Socket s = new Socket("127.0.0.1",48878);
            System.out.println("check 1");
            PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"));
            System.out.println("check 2");
            pw.write("Hello StackOverFlow.");
            System.out.println("check 3");
            pw.flush();
            System.out.println("check 4");
            while(true){}
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
服务器SSCCE

package testServer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {


    public static void main(String[] args) {
        try {
            ServerSocket ss = new ServerSocket(48878);
            Socket client = ss.accept();
            System.out.println("check 1");
            BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
            System.out.println("check 2");
            byte[] buffer = new byte[20];
            int i = 0;;
            int x;
            while((x=reader.read())!=-1) {
                buffer[i] += (byte)x;
                i = i++;
            }
            String text = new String(buffer,"UTF-8");
            System.out.println("check 3");
            System.out.println(text);
            client.close();
            ss.close();
        } catch (IOException  e) {
            e.printStackTrace();
        }
    }

}

调用新行方法后,尝试使用该函数的自动刷新属性刷新数据。在流中写入任何数据后,无需调用flush

PrintStream
类不同,如果启用了自动刷新,则仅当调用
println
printf
format
方法之一时,而不是在输出换行符时,才会执行自动刷新

示例代码:

客户:

PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"),true);
pw.println("Hello StackOverFlow.");
服务器:

BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
System.out.println(reader.readLine());

调用新行方法后,尝试使用该函数的自动刷新属性刷新数据。在流中写入任何数据后,无需调用flush

PrintStream
类不同,如果启用了自动刷新,则仅当调用
println
printf
format
方法之一时,而不是在输出换行符时,才会执行自动刷新

示例代码:

客户:

PrintWriter pw = new PrintWriter(new OutputStreamWriter(s.getOutputStream(),"UTF-8"),true);
pw.println("Hello StackOverFlow.");
服务器:

BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream(),"UTF-8"));
System.out.println(reader.readLine());
“bug”位于用于读取数据的循环中。只有当您关闭另一侧的流时,才会发送EOF。因此,尽管is可能已经向数组中添加了N个字节,但循环似乎仍然挂起

您需要做的是向服务器发送关于客户端将要发送的数据长度的提示。可以是字节数/字符数或终止字符(换行符)

在sender中,发送数据+提示,然后刷新

在接收器中,读取尽可能多的数据,而不是多读一个字节。这样,接收器就不会阻塞

在您的情况下,
reader.readLine()
只要在发送方上使用
println()
+flush,就应该可以工作。

在用于读取数据的循环中存在“bug”。只有当您关闭另一侧的流时,才会发送EOF。因此,尽管is可能已经向数组中添加了N个字节,但循环似乎仍然挂起

您需要做的是向服务器发送关于客户端将要发送的数据长度的提示。可以是字节数/字符数或终止字符(换行符)

在sender中,发送数据+提示,然后刷新

在接收器中,读取尽可能多的数据,而不是多读一个字节。这样,接收器就不会阻塞


在您的情况下,
reader.readLine()
只要在发件人上使用
println()
+flush,就应该可以工作。

+1对不起,对于Braj的回答,您不需要在邮件末尾添加换行符,但是,您的回答是正确的;几乎和Braj的一模一样。我不认为我可以添加两个答案。他的答案给出了一个解决方案,我的答案解释了为什么会发生。两种情况下你都有换行符。+1抱歉,根据Braj的回答,你不需要在邮件末尾添加换行符,但是,你的答案是正确的;几乎和Braj的一模一样。我不认为我可以添加两个答案。他的答案给出了一个解决方案,我的答案解释了为什么会发生。在这两种情况下,您都有一个线路提要。谢谢。我一定忽略了Javadoc中关于它必须是println、printf或format方法的部分+1谢谢。我一定忽略了Javadoc中关于它必须是println、printf或format方法的部分+1.