【问题标题】:Error while writing a big string on a socket ?在套接字上写入大字符串时出错?
【发布时间】:2011-10-12 14:53:00
【问题描述】:

各位朋友,大家好,

我正在尝试通过套接字连接发送一个长字符串,但我将它们分为两部分,因此在执行我的过程时出现错误。

在客户端我正在发送文件,

BufferedWriter bufferedOut = null;
BufferedReader in = null;
socket = new Socket("192.168.0.15",4444);
bufferedOut = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

bufferedOut.write(xmlInString, 0, xmlInString.length());

/**
* wait for response
*/

byte[] buf = new byte[10000];
int actualNumberOfBytesRead = socket.getInputStream().read(buf);
String responseLine = new String(buf, 0, actualNumberOfBytesRead);

在服务器中,

 BufferedReader in = null;
 PrintWriter out = null;
 in = new BufferedReader(new InputStreamReader(client.getInputStream()));
 out = new PrintWriter(client.getOutputStream(), true);

//get the input
 byte[] buf = new byte[10000];
 int actualNumberOfBytesRead = client.getInputStream().read(buf);
 line = new String(buf, 0, actualNumberOfBytesRead);
 //send back
 out.println(result);

我怎样才能把我的字符串作为一个部分?你能告诉我我在代码上的错误在哪里吗?

谢谢大家

【问题讨论】:

    标签: java sockets tcp bufferedreader bufferedwriter


    【解决方案1】:

    您将需要一个循环来重复从输入流中读取,每次将读取的数据连接在一起,直到到达字符串的末尾。

    编辑 - 更详细一点。如果您正在考虑传输多个此类字符串/文件,请参阅@arnaud 的答案。如果您想要发送 1 个大字符串,那么:

    1. 在发送方,创建输出流,发送数据(如您所做的那样),然后不要忘记再次关闭流(这也将执行刷新以确保发送数据通过电线,并通知另一端没有更多的数据来)。

    2. 在接收站点上,循环读取数据,直到输入流结束(read(buf) 返回 -1),每次将数据连接到一个大缓冲区中,然后关闭输入流。

    另外,请阅读我关于将文件作为字节而不是字符串发送的评论。这对于 XML 文件尤其重要,因为它有相当特殊的编码检测规则。

    【讨论】:

    • 你的意思是 (in server ) while (in.line != null) { line = line + in.line } 吗?
    • 基本上是的,不过最好使用 StringBuilder 来连接数据。注意:如果您发送的只是文件,我建议将其作为字节发送,而不是字符串,除非您非常确定您正确读取了它。否则您将遇到编码问题(例如,客户端将其读取为 ISO-xxx,尽管它实际上是一个 UTF-8 文件)。
    • 通过这样做,套接字在尝试读取更多字节时将简单地阻塞。 (它不知道流何时结束......除非你在另一边关闭它......无论如何,这很讨厌)
    • 好吧,我试着像我写的那样在 while 循环中逐行阅读,但它从来没有进入 while 循环!它总是在等待(in.line!= null)可能是什么问题? ?
    • @arnaud:这完全取决于是否打算发送多个字符串/文件。如果只需要一个文件传输(并且问题没有另外指出),那么发送者执行打开/发送/关闭是完全可以接受的,而接收者可以读取直到该流关闭。阻塞使代码更容易。
    【解决方案2】:

    使用 TCP 套接字时,您正在处理“流”。也就是说,默认情况下消息之间没有分隔符。按照您的操作,您可能会阅读消息的一部分,或者更糟的是,阅读的不仅仅是消息。

    最常见的处理方式是分隔您的消息。您可以使用 DataInputStream/DataOutputStream 将字符串编码为字节并使用第一个字节来指示它的长度。这样,它就知道它应该在接收端读取多少字节。

        DataOutputStream out = null;
        DataInputStream in = null;
        Socket socket = new Socket("192.168.0.15",4444);
        out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    
        out.writeUTF(xmlInString);
        out.flush(); // to ensure everything is sent and nothing is kept in the buffer.
    
        // wait for response
    
        String responseLine = in.readUTF();
    

    然后,相应地调整服务器代码。

    当使用带有套接字的Buffered 输出时,出于性能原因建议这样做,建议在您编写消息后使用flush(),以确保所有内容都实际通过网络发送并且缓冲区中没有任何内容。

    您最初的问题可能是因为您的消息需要多个 TCP/IP 数据包,并且在您的服务器中,您只读取了刚到达的第一个数据包。

    【讨论】:

      猜你喜欢
      • 2018-02-10
      • 1970-01-01
      • 1970-01-01
      • 2014-02-25
      • 2013-11-14
      • 2021-08-01
      • 2017-06-11
      • 2018-05-20
      • 1970-01-01
      相关资源
      最近更新 更多