2012-12-12 8 views
2

나는 클라이언트 서버를 만들고있다. 서버가 하드 코딩 된 파일을 보낼 수 있지만 클라이언트는 지정하지 않은 한 얻을 수 있습니다. 텍스트 파일 만 보내야합니다. 내가 아는 한 : 클라이언트가 먼저 파일 이름을 보낸 다음 서버가 아무 것도 복잡하게 보내지 만 모든 종류의 오류가 발생합니다.이 코드는 연결 재설정/소켓 닫힌 오류가 발생합니다. 주요 문제는 네트워킹을 연구 할 시간이별로 없다는 것입니다.자바 요청 파일, 파일 보내기 (클라이언트 - 서버)

악의를 가져다 주시면 감사하겠습니다.

EDIT. 스트림을 닫으면 소켓이 닫히고 그 이유는 무엇입니까? 그렇게해서는 안됩니다.

서버 측 :

InputStream sin=newCon.getInputStream(); 
    DataInputStream sdata=new DataInputStream(sin); 
    location=sdata.readUTF(); 
    //sdata.close(); 
    //sin.close(); 

File toSend=new File(location); 
byte[] array=new byte[(int)toSend.length()]; 
FileInputStream fromFile=new FileInputStream(toSend); 
BufferedInputStream toBuffer=new BufferedInputStream(fromFile); 
toBuffer.read(array,0,array.length); 

OutputStream out=newCon.getOutputStream(); //Socket-closed... 
out.write(array,0,array.length); 
out.flush(); 
toBuffer.close(); 
newCon.close(); 

클라이언트 측 :

int bytesRead; 
server=new Socket(host,port); 

OutputStream sout=server.getOutputStream(); 
DataOutputStream sdata=new DataOutputStream(sout); 
sdata.writeUTF(interestFile); 
//sdata.close(); 
//sout.close(); 

InputStream in=server.getInputStream();  //socket closed.. 
OutputStream out=new FileOutputStream("data.txt"); 
byte[] buffer=new byte[1024]; 
while((bytesRead=in.read(buffer))!=-1) 
{ 
    out.write(buffer,0,bytesRead); 
} 
out.close(); 
server.close(); 
+0

읽기 전에 System.out.println (sdata.available())을 사용해 보셨습니까? 어쩌면 아직 읽을 것이 없습니다. –

+0

코드가 멀리까지 실행되지 않는다 :/ – MustSeeMelons

+0

하지만 location = sdata.readUTF()에 연결이 설정되었는데 연결이 재설정되었다고 할 수 있습니까? 그 전에 말이야. –

답변

1

클라이언트 출력 스트림에 쓰는 동안 서버에서 청크에서 파일을 읽기보다는 임시 바이트 배열을 생성하고 메모리에 전체 파일을 읽어보십시오 . 요청한 파일이 큰 경우 어떻게해야합니까? 또한 finally 블록에서 서버 측의 새 소켓을 닫아서 예외가 발생하더라도 소켓이 닫힙니다.

서버 측 : 당신이 Apache Common IOUtils 라이브러리를 사용하는 경우

Socket newCon = ss.accept(); 
    FileInputStream is = null; 
    OutputStream out = null; 
    try { 
     InputStream sin = newCon.getInputStream(); 
     DataInputStream sdata = new DataInputStream(sin); 
     String location = sdata.readUTF(); 
     System.out.println("location=" + location); 
     File toSend = new File(location); 
     // TODO: validate file is safe to access here 
     if (!toSend.exists()) { 
      System.out.println("File does not exist"); 
      return; 
     } 
     is = new FileInputStream(toSend); 
     out = newCon.getOutputStream(); 
     int bytesRead; 
     byte[] buffer = new byte[4096]; 
     while ((bytesRead = is.read(buffer)) != -1) { 
      out.write(buffer, 0, bytesRead); 
     } 
     out.flush(); 
    } finally { 
     if (out != null) 
      try { 
       out.close(); 
      } catch(IOException e) { 
      } 
     if (is != null) 
      try { 
       is.close(); 
      } catch(IOException e) { 
      } 
     newCon.close(); 
    } 

은 다음 스트림에 파일을 읽기/쓰기 코드의 상당 부분을 줄일 수 있습니다. 여기에서 5 줄에서 1 줄까지. 원격 클라이언트 절대 경로로 파일을 제공하는 서버를 갖는 잠재적으로 위험하고 대상 파일은 주어진 디렉토리 제한 및/또는 파일 형식 설정되어야 함은

org.apache.commons.io.IOUtils.copy(is, out); 

참고. 인증되지 않은 클라이언트에게 시스템 레벨 파일을 제공하고 싶지는 않습니다.

관련 문제