2015-01-14 6 views
0

У меня есть клиент и сервер, классический пример, который пытается очень просто проложить HTTP-протокол. Во-первых, клиент отправляет данные, пока сервер печатает данные, а затем наоборот. В следующем коде сервер или клиент блокирует по неизвестной причине. Клиент отправляет данные сервера, сервер получает данные и распечатывает их. Но он просто блокирует после печати данных. Если я закрываю выходной поток клиента (out.close()), клиент должен получить данные сервера, но вместо этого выдает сообщение IOException с сообщением: Socket закрыт.Простой сервер/клиентский сокет: БЛОКИРОВКА - Java

Мой вопрос, почему он блокирует? Должен ли я запускать вывод с помощью EOS?

КЛИЕНТ

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());} 
    } 
} 

SERVER

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 попробуйте создать строку «exit». Если сервер читает строку выхода, признайте, что ему нужно прекратить находиться в цикле 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 соединение обычно остается открытым какое-то время, клиент знает, чтобы прекратить чтение после того, как было получено достаточное количество байтов в соответствии с заголовком Content-length).

Смежные вопросы