2015-01-14 108 views
0

我有一个客户端和一个服务器,一个经典的例子,试图以非常简单的方式模拟http协议。首先,客户端在服务器打印数据时发送数据,然后发送数据。在下面的代码中,无论是服务器还是客户端块,原因不明。 客户端向服务器发送数据,服务器接收数据并打印它。但是在打印数据之后它会阻塞。如果关闭客户端的输出流(out.close()),则客户端应该获取服务器的数据,但是会抛出IOException异常,并显示消息:Socket关闭。简单的服务器/客户端套接字:阻塞 - Java

我的问题是为什么它阻止?我是否必须用EOS触发输出?

CLIENT

import java.nio.*; 
import java.nio.channels.*; 
import java.net.*; 
import java.util.*; 
import java.io.IOException; 
import java.io.*; 


public class block_client_webclient 
{ 
    public static void main(String [] args) 
    { 
     try{ 

      Socket s = new Socket("localhost", 8080); 

      OutputStreamWriter out = new OutputStreamWriter(s.getOutputStream()); 
      InputStreamReader in = new InputStreamReader(s.getInputStream()); 

      //WRITE 
      out.write("GET/HTTP/1.1\r\nUser-agent: Agent 2.0 Browser\r\nAccept: */*\r\nAccept-Language: en-US,en;q=0.5\r\nConnection: keep-alive\r\n\r\n"); 
      out.flush(); 
      out.close(); 

      if (s.isConnected()==true && s.isClosed()==false) System.out.println("OPEN"); 
      else System.out.println("CLOSED"); 

      char[] bin = new char[400]; 
      int r=0; 

      //READ 
      while((r=in.read(bin))!=-1) { System.out.println("Input data: "+r+" bytes"); System.out.print(bin); bin= new char[400]; }; 
      System.out.println(r); 

      s.close(); 

     } 
     catch (IOException ex) {System.out.println(ex.getMessage());} 
    } 
} 

服务器

import java.nio.*; 
import java.nio.channels.*; 
import java.net.*; 
import java.util.*; 
import java.io.IOException; 
import java.io.*; 


public class block_server_webserver 
{ 
    public static void main(String [] args) 
    { 
     while(true) 
     { 
     try{ 
      ServerSocket server = new ServerSocket(8080); 
      Socket connection = server.accept(); 
      try{ 
      OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream()); 
      InputStreamReader in = new InputStreamReader(connection.getInputStream()); 

      char[] bin = new char[400]; 
      int r=0; 
      int readsofar=0; 

      //READ 
      while((r=in.read(bin))!=-1) { System.out.print(bin); bin= new char[400]; }; 
      System.out.println("END"); 

      //WRITE 
      out.write("Server: BlockServer 1.0\r\nHost: 192.168.1.1\r\n\r\n"); 
      out.flush(); 
      System.out.println("Just written data to "+connection.getRemoteSocketAddress()); 
      connection.close(); 

      } catch (IOException ex) { connection.close();} 
     }catch (IOException ex) {} 
    } 
    } 
} 

回答

2

执行out.close()会导致套接字关闭异常,因为当关闭输入/输出流时,与其关联的套接字也会关闭。这意味着在您的客户端程序中,关闭套接字后将无法读入。

首先,取出out.close()而不是检查-1,尝试创建一个“退出”字符串。如果服务器读取出口字符串,则认识到它需要停止在while循环中并且只是中断; (可以用简单的if语句来完成)。此外,通常我会使用缓冲读取器,String x和readLine()而不是char数组+ read()。

while (true) { 
    in.read(bin); 
    if (bin[0] == '^') { // or something like that 
     break; 
    } 
    System.out.print(bin); 
    bin = new char[400]; 
} 

完全使用套接字时只关闭()流。

2

服务器不应该等待套接字关闭掉(因为,一旦出现这种情况,就无法回写)。

而不是读取,直到它返回-1(关闭),它应该读取到请求的结尾(在http头的情况下两个新行),并开始发送输出一旦发生,那么,可能,关闭该连接通知客户端没有更多数据(在http中,连接通常保持打开一段时间,客户端知道在根据内容长度头接收到足够的字节后停止读取)。