2017-02-20 39 views
0

我试图让简单的服务器客户端应用程序,可以让客户端发送一个文件到服务器,然后服务器发送它接收到的文件java的插座连接复位

这是服务器级的确认消息。

public class Server { 

public static void main(String[] args) { 
    try { 
     ServerSocket server=new ServerSocket(9090); 
     while(true){ 
      Socket clientSocket=server.accept(); 
      ClientThread client=new ClientThread(clientSocket); 
      client.start(); 
     } 
    } catch (IOException e) { 
     System.out.println(e.toString()); 
    } 

} 

} 

ClientThread类

public class ClientThread extends Thread { 

private Socket socket;// socket to connect through 
private BufferedInputStream SocketInput;// stream to read from socket 
private BufferedOutputStream FileOutput;// stream to write file through it 
private PrintWriter SocketOutput; // print writer to write through socket 

public ClientThread(Socket socket){// constructor 
    this.socket=socket; 
} 

public void run(){ 
    try { 
     //get socket input stream 
     SocketInput=new BufferedInputStream(socket.getInputStream()); 

     //get socket output stream 
     SocketOutput=new PrintWriter(socket.getOutputStream(),true); 

     // get the file from client 
     int NBytes=0; 
     byte[] data=new byte[1024]; 

     FileOutput=new BufferedOutputStream(new FileOutputStream("C:/Users/mohamed/Desktop/Download/band.jpg"));  
     while((NBytes=SocketInput.read(data))!=-1){ 
      FileOutput.write(data,0,NBytes); 
      FileOutput.flush(); 
     } 

     // send ack. that file has been received 
     SocketOutput.println("File has been sent sucessfully"); 

     //close all streams 
     FileOutput.close(); 
     SocketInput.close(); 
     SocketOutput.close(); 
     socket.close(); 

    } 
    catch (IOException e) { 
     System.out.println(e.toString()); 
    } 
} 
} 

Client类

public class Client { 

public static void main(String[] args) { 

    // file will be sent 
    File f=new File("D:/images/band.jpg"); 

    try { 

     // get address of local host 
     InetAddress serverAddress=InetAddress.getLocalHost(); 

     //create socket 
     Socket socket=new Socket(serverAddress,9090); 

     // create streams 
     BufferedInputStream input=new BufferedInputStream(new FileInputStream(f)); 
     BufferedOutputStream output=new BufferedOutputStream(socket.getOutputStream()); 
     BufferedReader p=new BufferedReader(new InputStreamReader(socket.getInputStream())); 

     // send the file 
     byte[] data=new byte[1024]; 
     int Nbytes=0; 

     while((Nbytes=input.read(data))!=-1){ 
      output.write(data,0,Nbytes); 
      output.flush(); 
     } 

     // read the ack. and print it 
     System.out.println(p.readLine()); 

     //close streams & socket 
     p.close(); 
     input.close(); 
     output.close(); 
     socket.close(); 

    } catch (UnknownHostException e) { 
     e.printStackTrace(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

} 

我所得到的,当我运行在服务器和客户端我没有什么,如果我停止客户端服务器应用程序的类型控制台异常连接重置,但如果我删除了部分确认文件已收到并且没有任何错误,那么问题是什么?

回答

-1

因为如果你有连接侧的这样的代码

while((Nbytes=input.read(data))!=-1){ 
     output.write(data,0,Nbytes); 
     output.flush(); 
    } 

    // read the ack. and print it 
    System.out.println(p.readLine()); 

您将阻止在最后一行并等待输入。但由于插座仍在打开你的阅读端代码

while((NBytes=SocketInput.read(data))!=-1){ <-- HERE U ARE BLOCKED 
     FileOutput.write(data,0,NBytes); 
     FileOutput.flush(); 
    } 

将阻止对while循环条件。在连接有效并且输入未关闭之前,#read将不会返回,因此您将阻止。

试图关闭输出流的所有内容transmited

while((Nbytes=input.read(data))!=-1){ 
     output.write(data,0,Nbytes); 
     output.flush(); 
    } 
    output.close(); // this should unblock blocked thread on the other side 
    // read the ack. and print it 
    System.out.println(p.readLine()); 

这之后应该有效地告诉对方,没有其他的数据将被transmited(阻塞读取方法将返回-1)

+0

关闭输出流关闭套接字,所以下面的readLine'()'会得到一个“窝”封闭例外。 – EJP

0

你'陷入僵局。客户端正在读取套接字以结束数据流,并且您尚未关闭套接字,因此没有数据流结束,因此当您读取ACK行时,两个对等端都正在读取数据。

您不需要ACK线。只要删除它。不要发送它,也不要阅读它。

+0

我在客户类 System.out.println(p.readLine())中读取此行中的ACK;其中 –

+0

你读的ACK线,而你的服务器仍在等候流的末尾p被缓冲的读者自己的'阅读()'。 – EJP