从尚未关闭的服务器套接字读取所有字符串

时间:2016-03-04 07:37:41

标签: java python sockets readline

我在Java中使用套接字编程时遇到问题。 有一个像python这样的服务器,我不应该改变它。

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send('from server\nnewline\0')
data = s.recv(BUFFER_SIZE)
s.close()

现在我想用Java编写一个从服务器读取字符串的代码。像这样:

public static String readStr(Socket client) throws IOException {
        InputStreamReader inStream = new InputStreamReader(
                client.getInputStream());
        BufferedReader inBuff = new BufferedReader(inStream);
        String answer = new String();
        String str = inBuff.readLine();
        while (str!=null) {
            answer = answer.concat(str + "\n");
            str = inBuff.readLine();
        }
        answer = answer.substring(0, answer.length() - 1);
        System.out.println("answer:\n "+answer);
        return answer;
    }

但它似乎在消息的最后一行阻止了str = inBuff.readLine();行。我尝试了read()方法,但它也被阻止了。

3 个答案:

答案 0 :(得分:0)

这可能是因为服务器发送的最后一行没有结束,readLine()方法只在到达行尾时返回。因为您更改了服务器的代码。我建议您使用另一种方法从流中读取。您也可以使用InputStreamReader类。

答案 1 :(得分:0)

在tcp上设计协议时,最好的方法是包含某种成帧器。这是通过使用 NUL 字节在当前协议中完成的。

从套接字读取数据时,在解析各个块之前,应先通过某些操作将其划分为块/帧。

将数据包分成块的粗略方法是读取,直到找到 NUL 字节,然后将该块作为字节数组返回。 (这不是最有效的实现)

public byte[] readPacket(InputStream in) throws IOException {
     ByteArrayOutputStream tempStr = new ByteArrayOutputStream();
     int read;
     read=in.read();
     while(read > 0){
       tempStr.write(read);
       read=in.read();
       }
     if(read == -1)
         throw new EOFException();
     return tempStr.toByteArray();
}

因为您现在拥有适当的数据框架,所以现在可以轻松读取数据:

byte[] frame = readPacket(in);
String[] lines = new String(frame, StandardCharsets.UTF8).split("\n");
// Do something with the lines

答案 2 :(得分:0)

除了已经提到的不一致的消息/行结束 - 一次使用\n,第二次使用\0,在服务器上没有检测到消息的结束。因此,只要套接字未在客户端关闭(或关闭以进行写入),服务器就会循环。因为你在关闭套接字之前有这一行:

data = s.recv(BUFFER_SIZE)

换句话说,客户端正在等待来自服务器的一些响应。但是服务器永远停留在循环中从客户端读取消息。

因此,您需要在recv调用之前关闭套接字或发送一些消息(如空行)并在服务器上检测并最终退出循环。