2012-06-14 2 views
0

클라이언트가 서버에 데이터 (예 : 영화)를 보내는 클라이언트 서버 상황이 발생하면 서버는 해당 데이터를 HDD에 저장합니다.TCP를 통한 데이터 전송

고정 된 바이트 배열로 데이터를 보냅니다. 바이트가 전송 된 후 서버는 더 많은 메시지가 있는지 묻습니다. 모든 일이 잘 진행되고 모든 데이터가 전달됩니다.

그러나 영화를 재생하려고하면 재생할 수 없으며 각 영화 (클라이언트 및 서버)의 파일 길이를 보면 서버 동영상이 클라이언트 영화보다 커집니다. 명령을 보면 화면에는 송수신 데이터의 끝 부분에 100 % 이상의 바이트가 있습니다.

내가 잘못 생각할 수있는 유일한 점은 고정 버퍼 배열이 가득 찰 때까지 내 서버가 스트림에서 읽는 것이므로 결국 바이트 수보다 많은 클라이언트가 있다는 것입니다. 그러나 이것이 문제라면 어떻게 해결할 수 있습니까?

TCP 연결이 작동하기 때문에 나는 2methods를 추가했습니다. 어떤 도움도 환영합니다.

클라이언트

public void SendData(NetworkStream nws, StreamReader sr, StreamWriter sw) 
{ 
    using (FileStream reader = new FileStream(this.path, FileMode.Open, FileAccess.Read)) 
    {     
     byte[] buffer = new byte[1024]; 
     int currentBlockSize = 0; 

     while ((currentBlockSize = reader.Read(buffer, 0, buffer.Length)) > 0) 
     { 
      sw.WriteLine(true.ToString()); 
      sw.Flush(); 
      string wait = sr.ReadLine(); 
      nws.Write(buffer, 0, buffer.Length); 
      nws.Flush(); 
      label1.Text = sr.ReadLine(); 
     } 
     sw.WriteLine(false.ToString()); 
     sw.Flush();     
    } 
} 

서버

private void GetMovieData(NetworkStream nws, StreamReader sr, StreamWriter sw, Film filmInfo) 
    { 
     Console.WriteLine("Adding Movie: {0}", filmInfo.Titel); 
     double persentage = 0; 

     string thePath = this.Path + @"\films\" + filmInfo.Titel + @"\"; 
     Directory.CreateDirectory(thePath); 

     thePath += filmInfo.Titel + filmInfo.Extentie; 

     try 
     { 
      byte[] buffer = new byte[1024]; //1Kb buffer 

      long fileLength = filmInfo.TotalBytes; 
      long totalBytes = 0; 

      using (FileStream writer = new FileStream(thePath, FileMode.CreateNew, FileAccess.Write)) 
      { 
       int currentBlockSize = 0; 
       bool more; 
       sw.WriteLine("DATA"); 
       sw.Flush(); 
       more = Convert.ToBoolean(sr.ReadLine()); 


       while (more) 
       { 
        sw.WriteLine("SEND"); 
        sw.Flush(); 
        currentBlockSize = nws.Read(buffer, 0, buffer.Length); 
        totalBytes += currentBlockSize; 
        writer.Write(buffer, 0, currentBlockSize); 

        persentage = (double)totalBytes * 100.0/fileLength; 
        Console.WriteLine(persentage.ToString()); 

        sw.WriteLine("MORE"); 
        sw.Flush(); 
        string test = sr.ReadLine(); 
        more = Convert.ToBoolean(test);      
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.ToString()); 
     } 
    } 

답변

2

Read()는 읽은 바이트 수를 반환 이유가있다 : 그것은 버퍼의 크기보다 적은을 반환 가능합니다. 이 때문에 SendData()nws.Write(buffer, 0, currentBlockSize);과 같은 것을해야합니다. 하지만 블록이 더 이상 크기를 가지지 않으므로 프로토콜이 중단됩니다.

하지만 코드가 실제로 당신이 묘사하는 방식으로 행동한다고 ​​믿는 것이 어렵습니다. GetMovieData()Read()도 전체 버퍼를 채울 수 없기 때문입니다. 또한 StreamReader은 내부 버퍼에 일부 데이터를 보관할 수 있습니다. 이는 완전히 가짜 데이터를 읽을 수 있음을 의미합니다.

이 코드는 StreamStreamReader s/StreamWriter을 결합하는 코드는 매우 나쁜 생각입니다. 그것은 실제로 그것을 정확하게 만드는 것이 어려울 것입니다. 대신 바이트가 ASCII로 인코딩 된 "SEND" 인 경우에도 프로토콜을 완전히 바이트 기반 (문자 기반이 아님)으로 만드는 것이 좋습니다.

0

날이 를 시도해 보자하지만 작동하지 않는 경우 나를 쏘지 마세요.

보내는 파일에 남아있는 바이트 수에 관계없이 버퍼 크기가 1024 인 것을 알았습니다. 3 번 보내야하는 2900 바이트의 파일이 있다고 가정 해 보겠습니다. 보내려는 마지막 파일은 852 바이트 만 남았습니다. 그러나 1024 버퍼를 만들고 1024 바이트 이상을 보냅니다. 즉, 서버에 852 바이트의 실제 데이터와 172 개의 0으로 채워진 바이트가 수신됩니다. 그럼에도 불구하고 모든 172 바이트는 서버의 동영상 파일에 저장됩니다.

쉽게 해결할 수 있습니다. 서버에 데이터를 쓸 때 길이로 인수로 currentBlockSize을 사용하십시오.그래서 클라이언트 방법 SendData에, while 루프 내부에 변경이에

nws.Write(buffer, 0, buffer.Length); 

:

nws.Write(buffer, 0, currentBlockSize); 
+0

버퍼의 나머지 바이트를 제로되지 않습니다, 그들은의 이전 내용이 될 것입니다 버퍼 – svick