2012-01-26 4 views
1

소켓 프로그래밍 C# (.NET)에서 직접 노력하고 있습니다. codeproject에서 몇 가지 예제를 언급했지만 파일 전송은 항상 불완전한 데이터를 보냅니다.소켓 파일 전송 C#에서 불완전한 파일 보내기

아주 작은 크기의 데이터는 1kB처럼 잘 작동합니다. 그러나 큰 파일은 불완전한 이미지, 특히 이미지가 전송됩니다.

내 클라이언트 코드는 서버에 파일을 보냅니다. clientData는 파일의 바이너리를 저장합니다.

byte[] fileData = File.ReadAllBytes(filePath + fileName); 
      byte[] clientData = new byte[4 + fileNameByte.Length + fileData.Length]; 
      byte[] fileNameLen = BitConverter.GetBytes(fileNameByte.Length); 

      fileNameLen.CopyTo(clientData, 0); 
      fileNameByte.CopyTo(clientData, 4); 
      fileData.CopyTo(clientData, 4 + fileNameByte.Length); 

      curMsg = "Connection to server ..."; 
      clientSock.Connect(ipEnd); 
      int count; 
      curMsg = "File sending..."; 
      count = clientSock.Send(clientData); 
      MessageBox.Show(count+" "+clientData.Length); 

      curMsg = "Disconnecting..."; 
      clientSock.Close(); 

여기 동안 파일을 수신하는 서버에 대한 내 코드입니다.

   sock.Listen(100); 

      curMsg = "Running and waiting to receive file."; 
      Socket clientSock = sock.Accept(); 

      byte[] clientData = new byte[1024 * 5000]; 

      int receivedBytesLen = clientSock.Receive(clientData); 
      curMsg = "Receiving data..."; 

      int fileNameLen = BitConverter.ToInt32(clientData, 0); 
      string fileName = Encoding.ASCII.GetString(clientData, 4, fileNameLen); 

      BinaryWriter bWrite = new BinaryWriter(File.Open(receivedPath +"/"+ fileName, FileMode.Append)); ; 
      bWrite.Write(clientData, 4 + fileNameLen, receivedBytesLen - 4 - fileNameLen); 

      curMsg = "Saving file..."; 

      bWrite.Close(); 
      clientSock.Close(); 

재미있는 점은 클라이언트에서 '보내기'에서 중단 점을 설정하면 파일이 올바르게 전송된다는 것입니다. 내가 수신 바이트가 클라이언트에서 전송 된 바이트보다 낮은 동안 내가 중단 점을 사용할 때 양끝에서 바이트 수와 전송 바이트가 일치하는 것을 관찰하고 있습니다.

내가 뭘 잘못하고 있니?

+0

데이터를 청크 단위로 보내려면 작성한 코드를 업로드 할 수 있습니까? – AndroidLearner

+0

사용중인 Close()의 오버로드는 "완료"로 보내기/받기를 기다리지 않고 시간 초과가있는 오버로드를 사용해야하므로 나가는 스트림을 "제거"할 시간이 있습니다. –

답변

2

프로토콜을 구현하는 것을 잊었습니다! TCP를 사용하려면 전송할 바이트와 수신자가 메시지 또는 프로토콜 데이터 요소를 식별하는 방법을 정의하는 프로토콜을 설계하고 구현해야합니다. 너는이 일을하지 않았다. 수신 코드에는 전체 파일을 받았는지 여부를 알 수있는 방법이 없습니다. 프로토콜을 알리거나 알맞은 프로토콜을 구현할 코드가 없기 때문입니다. 그래서 물론 잘못된 것입니다. 제대로 할 수있는 방법이 없습니다.

receivedBytesLen이 1이면 코드가 끔찍하게 실패합니다.

+0

안녕하세요. 소켓 초기화에 다음 코드를 사용하고 있는데, ProtocolType.IP가 도움이된다고 가정했습니다. 'ipEnd = new IPEndPoint (IPAddress.Any, 5656); sock = 새로운 소켓 (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); sock.Bind (ipEnd); ' –

+0

ProtocolType.Ip를 ProtocolType.Tcp로 변경했습니다. 아직도 운이 없다. 나는 절대적인 초보자이고, 당신을 구체적으로 기쁘게 할 수 있습니다. –

+0

당신은 내 대답을 전혀 이해하지 못했습니다. 파일을 보내려고합니다. TCP는 파일 전송 프로토콜이 아니며 바이트 전송 프로토콜입니다. 파일을 전송하려면 파일 전송 프로토콜이 필요합니다. 한 줄의 코드라도 작성하기 전에 그러한 프로토콜을 디자인하고 문서화해야합니다. –

1

기본 네트워크 또는 TCP 계층이 전체 파일을 하나의 단일 청크로 보낼 수있는 것은 아닙니다. 파일의 정확한/완전한 길이를받을 때까지 while 루프를 시도 할 수 있습니다.

이렇게하려면 파일의 길이를 먼저 보내야 할 수 있습니다.

예, 디버그 모드에서 작동하지만 런타임 중에는 다를 수 있습니다.

+0

Thanks Muthu, 먼저 파일 크기를 하드 코딩 해 보았습니다. 비트를 올바르게 수신했습니다. 버퍼가 덮어 쓰기됩니다. –

+0

예, 이것을 다른 바이트 배열 또는 List 에 추가해야하며 이후에 덮어 써서는 안됩니다. – Muthu