2016-03-04 74 views
1

我在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()方法,但它也被阻止。

回答

0

在通过tcp设计协议时,最好的方法是包含某种成帧器。这是在当前协议中通过使用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 
0

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

+0

我已经使用了nputStreamReader类。你推荐哪种方法? @ user6015630 – user63835

+0

你可以在BufferedReader中使用read(char [] cbuf,int off,int len) – user6015630

0

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

data = s.recv(BUFFER_SIZE) 

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

所以,你需要要么关闭套接字recv呼叫前或发送一些信息(如空行),并检测在服务器上,并最终退出循环。

相关问题