【问题标题】:Unable to write data through BufferedWriter on Socket无法通过 Socket 上的 BufferedWriter 写入数据
【发布时间】:2016-10-12 09:03:02
【问题描述】:

在将此标记为可能重复之前,请先阅读一次,因为我找不到任何答案。我正在学习套接字编程并使用套接字创建一个非常基本的服务器-客户端文件传输程序。 这是我的服务器模块:

import java.io.*;
import java.net.*;
import static java.lang.System.out;

public class ServerMain {
    public static void main(String[] args) {
    int PORT=13267;
    ServerSocket servSocket;
    Socket client;
    File source=new File("E:/Styles of Beyond.wav");;
    BufferedInputStream bis;
    BufferedReader br;
    String s="";
    InputStream is;
    byte[] byteBuffer=new byte[10240];
    OutputStream os;
    int count=0;

    try{

        servSocket=new  ServerSocket(PORT);
        out.println("Server running on port: "+PORT+", waiting for client...");
        client=servSocket.accept();
        client.setKeepAlive(true);
        out.println("Client: "+client.getRemoteSocketAddress()+" connected. Sending file...");
        bis=new BufferedInputStream(new FileInputStream(source));
        os=client.getOutputStream();
        is=client.getInputStream();

        while((count=bis.read(byteBuffer))>0){
            os.write(byteBuffer, 0, count);
        }

        out.println("Waiting for confirmation from client...");
        br=new BufferedReader(new InputStreamReader(is));
        if(br.readLine()=="Done")
            out.println("Done.");
        else
            out.println("Couldn't get confirmation from server.");
    }

    catch(Exception e)
    {
        e.printStackTrace();
    }
}
}

还有客户端模块:

import static java.lang.System.out;
import java.io.*;
import java.net.*;

public class ClientMain {

    public static void main(String[] args) {
        int SERV_PORT=13267;
        Socket server;
        File destination=new File("E:/copy.wav");
        byte[] byteBuffer=new byte[10240];
        InputStream is;
        OutputStream os;
        BufferedWriter bw;
        int count=0;

        try{
            out.println("Tyring to connect to server...");
            server=new Socket("localhost",SERV_PORT);
            out.println("Connected to server: "+server.getRemoteSocketAddress());
            is=server.getInputStream();
            os=server.getOutputStream();
            out.println("Receiving data...");
            BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(destination));

            while((count=is.read(byteBuffer))>0){
                bos.write(byteBuffer, 0, count);
            }
            bw=new BufferedWriter(new OutputStreamWriter(os));
            bw.write("Done");
            bw.newLine();
            out.println("Data successfully written to copy.wav");
        }
        catch(Exception e){
            e.printStackTrace();
        }
}
}

代码可以正常工作,甚至文件copy.wav也可以正确创建,但是在客户端的操作系统上写入后,服务器卡在“等待来自客户端的确认...”,客户端卡在“正在接收数据。 ……”。我尝试在客户端而不是 BufferedWriter 上使用 PrintWriter,并且还简单地尝试在 os 上写入单个字节,并在服务器端检查该字节以获取文件接收确认,但似乎没有任何效果,客户端没有发送任何内容。我注意到的一件事是,在服务器上调用 is.ready() 总是返回 false。

如果我在客户端和服务器上删除与发送和接收文件确认相关的所有代码,客户端程序会产生 SocketException: connection reset,因为现在服务器不会等待客户端完成其 is.read( ) 任务并在使用 os.write() 完成写入后立即关闭连接,这会创建具有小于原始数据大小的部分数据的 copy.wav。我该如何正确地做这件事?

P.S:我知道我没有关闭流并正确处理异常,但这似乎不是问题。

【问题讨论】:

  • 您不能在同一个套接字上混合缓冲流和读取器。他们会互相窃取数据。
  • @EJP 那么我应该在使用另一个之前关闭一个吗?
  • 我不明白投反对票的原因,问题还没有解决,下面发布的答案 xaxxon 对我不起作用......
  • 所以你应该使用其中一个。正如我已经说过的,不要混合它们。

标签: java sockets outputstream


【解决方案1】:

冲洗它!

https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#flush()

打电话后:

        bw.write("Done");
        bw.newLine();

操作系统正在等待更多,因此它可以有效地以大块的形式发送数据。

此外,您可以在其上设置 TCP_NODELAY,但您通常应该让操作系统来做这件事,因为它比您更了解在大多数情况下发送数据的最佳方式。

How does TCP_NODELAY affect consecutive write() calls?

【讨论】:

  • 刷新是必需的,因此操作系统甚至可以首先了解数据。不是因为 Nagke 算法。
  • 它仍然不起作用,我尝试在两者上刷新输出流:在 while 循环之后的服务器上,以及 bw.newLine() 之后的客户端上,如你所说,仍然卡在相同的状态:(
  • @xaxxon 有什么帮助吗?
  • 根据@EJP 所说的设置nodelay。
  • @xaxxon 这也不行!我通过在不同点写 out.println() 发现的另一件事是,虽然 while 循环到达结束,但它停留在最后一个 is.read() 上,控制永远不会在循环之后到达下一个语句,即使我m 在服务器上刷新输出流! wtf?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
  • 2012-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多