2017-03-08 41 views
0

我已经通过winsock2创建了一个服务器/客户端。如果客户端使用bmp截图,将其压缩成jpeg并将其发送到服务器。我遇到的问题是服务器在将文件保存到磁盘时遇到问题。像数据没有收到的权利。我认为它必须以我发送或接收缓冲区的方式进行。IStream COM读缓冲区,然后通过winsock发送

编辑:在调试过程中从设置breakpoints似乎好像所有的数据都收到。 istream->Write返回与Sizeistream->Seek返回S_OKCLSID相关的正确字节数,该对象包含与发送的数据相同的数据。在我发送缓冲区之前,我测试它是否保存并确实存在。因此,我假设它必须是缓冲区发送或接收的方式。

编辑: 两端缓冲看起来像This

屏幕快照加上发送代码。

ScreenShot(Packet_Handler* _Handle) 
{ 
IStream* istream; 
    //char* Buff; 
    HRESULT res = CreateStreamOnHGlobal(NULL, true, &istream); 
    Gdiplus::GdiplusStartupInput gdiInput; 
    ULONG_PTR gdiToken; 
    Gdiplus::GdiplusStartup(&gdiToken, &gdiInput, NULL); 
    { 
     HDC scrdc, memdc; 
     HBITMAP membit; 
     scrdc = ::GetDC(0); 
     int Height = GetSystemMetrics(SM_CYSCREEN); 
     int Width = GetSystemMetrics(SM_CXSCREEN); 
     memdc = CreateCompatibleDC(scrdc); 
     membit = CreateCompatibleBitmap(scrdc, Width, Height); 
     HBITMAP hOldBitmap = (HBITMAP)SelectObject(memdc, membit); 
     BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY); 

     Gdiplus::Bitmap bitmap(membit, NULL); 
     CLSID clsid; 
     GetEncoderClsid(L"image/jpeg", &clsid); 


     bitmap.Save(istream, &clsid, NULL); 
     bitmap.Save(L"Test.jpeg", &clsid, NULL); //THIS WORKS 
     STATSTG pstatstg = { 0 }; 
     istream->Stat(&pstatstg, 0); 
     ULONG Bytes; 
     char* isBuff = new char[pstatstg.cbSize.QuadPart]; 
     LARGE_INTEGER li; 
     li.QuadPart = 0; 
     istream->Seek(li, STREAM_SEEK_SET, NULL); 
     if (istream->Read(isBuff, pstatstg.cbSize.QuadPart, &Bytes) == S_OK) 
     { 
      IStream* nistream = nullptr; 
      ULONG nBytes; 
      CreateStreamOnHGlobal(NULL, true, &nistream); 
      if (nistream->Write(isBuff, pstatstg.cbSize.QuadPart, &Bytes) == S_OK) 
      { 

       if (nistream->Seek(li, STREAM_SEEK_SET, NULL) == S_OK) 

       { 
        Gdiplus::Bitmap bitmap2(nistream, NULL); 
        bitmap2.Save(L"Testing.jpeg", &clsid, NULL); //THIS WORKS 
       } 
      } 
     } 

     int Size = pstatstg.cbSize.QuadPart; 
     int SOLI = sizeof(ULARGE_INTEGER); 
     int SOCID = sizeof(CLSID); 
     int SOIS = sizeof(IStream); 

     Send_Full_Packet(_Handle, &Size, isBuff, TRUE); 
     Send_Full_Packet(_Handle, &SOCID, &clsid, FALSE); 



     printf("saving Screenshot"); 


     DeleteObject(memdc); 
     DeleteObject(membit); 
     ::ReleaseDC(0, scrdc); 

    } 
    Gdiplus::GdiplusShutdown(gdiToken); 
    _getch(); 
    return 0; 
} 
    void Send_Full_Packet(Packet_Handler* _Handle, int* pSize, void * Buff, bool ispchar) 
    { 
     int SentPackets = 0; 
     int sCheck = 0; 
     int rCheck = 0; 
     int Size = *pSize; 
     char* isBuff;// = new char[Size]; 

      sCheck = send(_Handle->ConnectSocket, (char*)&Size, sizeof(int), NULL); 

     int PacketsSent = 0; 
     sCheck = 0; 
     int PacketsLeft = Size; 
     while (PacketsSent < Size) 
     { 
      if (ispchar == FALSE) 
      { 
       SentPackets = send(_Handle->ConnectSocket, (char*)Buff + PacketsSent, PacketsLeft, NULL); 
      } 
      else { 
       isBuff = (char*)Buff; 
       SentPackets = send(_Handle->ConnectSocket, isBuff + PacketsSent, PacketsLeft, NULL); 
      } 
      if (SentPackets == SOCKET_ERROR) 
      { 
       if (WSAGetLastError() != 10054) 
       { 
        if (WSAGetLastError() == 10035) 
        { 
         SentPackets == 0; 

        } 
        else 
        { 
         printf("Sending Socket error: %d\n", WSAGetLastError()); 
         break; 
        } 

       } 
      } 
      PacketsSent += SentPackets; 
      PacketsLeft -= SentPackets; 
     } 


    } 

接收代码

ScreenShot_Receive_Thread(Packet_Handler* _Handle) 
{ 

    Packet_Handler::_Packet_Type Packet = Packet_Handler::_Packet_Type::Remote; 
    while (true) 
    { 
     if (send(_Handle->si.Connections[_Handle->si.ConnectionCounter - 1], (char*)&Packet, sizeof(Packet_Handler::_Packet_Type), 0) != INVALID_SOCKET) 
     { 
      while (true) 
      { 
       int Size = 0; 
       char* Buff = NULL; 
       Buff = _Handle->Receive_Full_Packet(_Handle, &Size, Buff, TRUE); 
       CLSID clsid; 
       int SOCID = sizeof(CLSID); 
       _Handle->Receive_Full_Packet(_Handle, &SOCID, &clsid, FALSE); 
       IStream* istream = nullptr; 
       ULONG Bytes; 
       CreateStreamOnHGlobal(NULL, true, &istream); 
       if (istream->Write(Buff, Size, &Bytes) == S_OK) 
       { 
        LARGE_INTEGER li; 
        li.QuadPart = 0; 
        if (istream->Seek(li, STREAM_SEEK_SET, NULL) == S_OK) 
        { 
         Gdiplus::Bitmap bitmap(istream, NULL); 
         bitmap.Save(L"Testing.jpeg", &clsid, NULL);//DOESNT WORK 
        } 
       } 

      } 
     } 
    } 
    MessageBox(NULL, L"CLient COnnection Error!", NULL, NULL); 
    return 0; 
} 


    char* Packet_Handler::Receive_Full_Packet(Packet_Handler * _Handle, int* pSize, void * Buff, bool ispchar) 
{ 
    int rCheck = 0; 
    int sCheck = 0; 
    int Size = *pSize; 
    rCheck = recv(_Handle->si.Connections[_Handle->si.ConnectionCounter - 1], (char*)&Size, sizeof(int), 0); 
    if (rCheck == -1) 
    { 
     int Error = WSAGetLastError(); 
     AllocConsole(); 
     freopen("CONOUT$", "w", stdout); 
     std::cout << "The Error is: " << Error << std::endl; 
    } 
    *pSize = Size; 
    char* isBuff;// = NULL; 
    int PacketsReceived = 0; 
    int PacketsLeft = Size; 
    int ReceivedPackets = 0; 
    while (PacketsReceived < Size) 
    { 
     if (ispchar == FALSE) 
     { 
      ReceivedPackets = recv(_Handle->si.Connections[_Handle->si.ConnectionCounter - 1], (char*)Buff + PacketsReceived, PacketsLeft, 0); 

     } 
     else 
     { 
      isBuff = new char[Size]; //I Think my problem is here// 

      ReceivedPackets = recv(_Handle->si.Connections[_Handle->si.ConnectionCounter - 1], isBuff + PacketsReceived, PacketsLeft, 0); 

     } 
     if (ReceivedPackets == SOCKET_ERROR) 
     { 
      int Error = WSAGetLastError(); 
      if (Error != 10054) 
      { 
       if (Error == 10035 || Error == 6) 
       { 
        ReceivedPackets == 0; 
       } 
       else 
       { 
        AllocConsole(); 
        freopen("CONOUT$", "w", stdout); 
        std::cout << "The Error is: " << Error << std::endl; 
        //MessageBox(NULL, (WCHAR*)WSAGetLastError(), NULL, NULL); 
        _getch(); 
        //return NULL; 
        break; 
       } 
      } 
     } 

     PacketsReceived += ReceivedPackets; 
     PacketsLeft -= ReceivedPackets; 
    } 
    return isBuff; 
} 
+0

您是否成功创建了'IStream' COM对象?即CreateStreamOnHGlobal'调用成功吗? –

+0

@Someprogrammerdude在接收端?我只是用'if(CreateStreamOnHGlobal(NULL,true,&istream)== S_OK)'检查它并成功。 –

回答

0

终于找出来了。发现我发送缓冲区的方式绝对没有错。它实际上是CLSID。我最终将GetEncoderClsid函数放在接收端。像黄油一样工作。

0

的数据可能需要多个recv调用接收充分。发生这种情况时,Receive_Full_Packet会为每个此类呼叫分配一个新缓冲区,并立即泄漏其中一个呼叫。它返回给调用者的是最后一个这样的分配 - 一个大多数未初始化的缓冲区,其中包含了随机垃圾,最后一块数据在最后。

isBuff = new char[Size];移至循环外部,将其放回第一个调用recv后检索大小。

+0

我会试试看。但从现在开始,因为我使用我的本地地址127.0.0.1来侦听,所以它一次性发送完整的缓冲区。 –

+0

那不是,而是谢谢你。如果它没有发送完整的数据包,那么这将会严重影响应用程序。 –