2013-09-06 4 views
1

제 프로젝트의 경우 클라이언트에서 스크린 샷을 찍어 소켓에서 서버로 보내려고합니다. 수동으로 멈출 때까지 루프를 사용하여 스크린 샷을 찍었습니다. 그러나 스크린 샷을 찍는 것이 좋지만 이미지를 전송 한 후에는 주 이미지의 절반 만되고 일부 이미지는 가득차 있습니다.
클라이언트 :
나는이
소켓을 통한 데이터 전송이 완료되지 않았습니다.

bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb); 
gfxScreenshot = Graphics.FromImage(bmpScreenshot); 
gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy); 
bmpScreenshot.Save(path + i + ".png"); 
ClientService.SendFile(path + i + ".png"); 
i++; 

과 sendfile을 방법으로 스크린 샷을 복용하고는

public static void SendFile(string fileName) 
     { 
      try 
      { 
       IPAddress[] ipAddress = Dns.GetHostAddresses("localhost"); 
       IPEndPoint ipEnd = new IPEndPoint(ipAddress[0], 5656); 
       Socket clientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 

       string filePath = ""; 

       fileName = fileName.Replace("\\", "/"); 
       while (fileName.IndexOf("/") > -1) 
       { 
        filePath += fileName.Substring(0, fileName.IndexOf("/") + 1); 
        fileName = fileName.Substring(fileName.IndexOf("/") + 1); 
       } 

       byte[] fileNameByte = Encoding.ASCII.GetBytes(fileName); 
       if (fileNameByte.Length > 600 * 1024) 
       { 
        showMsg = "File size is more than 600kb, please try with small file."; 
        return; 
       } 

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

       clientSock.Connect(ipEnd); 
       clientSock.Send(clientData); 
       clientSock.Close(); 

      } 
      catch (Exception ex) 
      { 
       if (ex.Message == "No connection could be made because the target machine actively refused it") 
        showMsg = "File Sending fail. Because server is not running."; 
       else 
        showMsg = "File Sending fail." + ex.Message; 
      } 
     } 

서버

IPEndPoint ipEnd; 
    Socket sock; 
    public ServerService() 
    { 
     ipEnd = new IPEndPoint(IPAddress.Any, 5656); 
     sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); 
     sock.Bind(ipEnd); 
    } 

    public static string receivedPath; 
    internal void StartServer() 
    { 
     try 
     { 
      sock.Listen(100); 

      Socket clientSock = sock.Accept(); 

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

      int receivedBytesLen = clientSock.Receive(clientData); 

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

      bWrite.Close(); 
      clientSock.Close(); 
     } 
     catch (Exception ex) 
     { 
      ShowMsg = "Something is wrong." + ex.Message; 
     } 
    } 

호입니다 이 문제를 해결할 수 있습니까?

답변

2

Receive은 (하나의) 보장 :

  • 창 적어도 1 바이트
  • 신호 EOF를 (비 양성 바이트)
  • 신호 에러

그것을 Receive 번으로 전화하면 충분하지 않습니다. 당신은 때까지 루프에 를 호출해야 하나 : 당신이 모든 데이터를 읽고

  • 당신이
  • 당신이 오류를

를 얻을 EOF를 얻을

  • 을하려는 예를 들면 다음과 같습니다.

    • 정확히 4 바이트 (루프가 필요할 수 있음)의 이름 길이를 얻으려면 01을 입력하십시오.
    • 다음 당신은 EOF (Receive의 비 긍정적 인 결과) 또한

    을 얻을 때까지 읽을 이름을

  • 를 읽고 정확히 n 바이트를 읽어 : 당신은 아마 Stream 기반 API를 사용하려면 File.ReadAllBytes 또는 BinaryWriter 대신 파일 액세스 (읽기 및 쓰기)가 필요합니다. 정확히n 바이트를 읽기

    같은 무언가의 경우입니다 : 또한

    public void ReceiveExactly(Socket socket, byte[] buffer, int offset, int count) 
    { 
        int read; 
        while(count > 0 && (read = socket.Receive(buffer, offset, count, 
         SocketFlags.None)) > 0) 
        { 
         offset += read; 
         count -= read; 
        } 
        if(count != 0) throw new EndOfStreamException(); 
    } 
    
  • +0

    , 나는 종료를 호출 생각하면 데이터가 실제로 발생한 것을 확인하기 위해 송신 측에서 필요하다. – usr

    +0

    @usr send 코드는'Close()'를 수행하는데 충분하다. 'Shutdown '은 * inbound * 파이프를 들으면서 * outbound * pipe를 닫고 싶을 때 편리하다. –

    +0

    마지막 바이트가 수신 확인 될 때까지 기다리지 못합니까? 문서는 매우 드문 드문 있습니다. NetworkStream.닫기는 종료 (둘 다); 닫기; – usr

    관련 문제