客户端通过TCP套接字的图像处理失败

时间:2017-04-07 11:43:47

标签: c# c++ sockets tcp

我正在开发一个通过TCP套接字查看客户端屏幕的应用程序。我的服务器应用程序在C#中,客户端应用程序在C ++中。我可以将图像发送到服务器而不会出现任何错误。在服务器端,在转换缓冲区长度时,我得到一个大数字,这会导致“溢出异常”,同时制作具有该大小的图像缓冲区。以下是我尝试的代码。

服务器代码

==========

public static void StartListening()
{
    // Data buffer for incoming data.
    byte[] bytes = new Byte[1024];

    // Establish the local endpoint for the socket.
    // The DNS name of the computer
    // running the listener is "host.contoso.com".
    IPHostEntry ipHostInfo = Dns.GetHostEntry("127.0.0.1");
    IPAddress ipAddress = ipHostInfo.AddressList[0];
    IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);

    // Create a TCP/IP socket.
    Socket listener = new Socket(AddressFamily.InterNetwork,
        SocketType.Stream, ProtocolType.Tcp);

    // Bind the socket to the local endpoint and listen for incoming connections.
    try
    {
        listener.Bind(localEndPoint);
        listener.Listen(100);

        while (true)
        {
            // Set the event to nonsignaled state.
            allDone.Reset();

            // Start an asynchronous socket to listen for connections.
            Console.WriteLine("Waiting for a connection...");
            listener.BeginAccept(
                new AsyncCallback(AcceptCallback),
                listener);

            // Wait until a connection is made before continuing.
            allDone.WaitOne();
        }

    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }

    Console.WriteLine("\nPress ENTER to continue...");
    Console.Read();

}

public static void AcceptCallback(IAsyncResult ar)
{
    // Signal the main thread to continue.
    allDone.Set();

    // Get the socket that handles the client request.
    Socket listener = (Socket)ar.AsyncState;
    Socket handler = listener.EndAccept(ar);

    // Create the state object.
    StateObject state = new StateObject();
    state.workSocket = handler;
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
        new AsyncCallback(ReadHeaderCallback), state);
}

public static void ReadHeaderCallback(IAsyncResult ar)
{
    // Retrieve the state object and the handler socket
    // from the asynchronous state object.
    StateObject state = (StateObject)ar.AsyncState;
    Socket handler = state.workSocket;

    // Read data from the client socket. 
    int bytesRead = handler.EndReceive(ar);

    //we need to add error handler here...but later
    state.ImageSize = BitConverter.ToInt32(state.buffer, 0);
    _imageBuff = new byte[state.ImageSize];
    _totBytesRead = 0;
    handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
       new AsyncCallback(ReadCallback), state);
}

public static void ReadCallback(IAsyncResult ar)
{
    String content = String.Empty;

    // Retrieve the state object and the handler socket
    // from the asynchronous state object.
    StateObject state = (StateObject)ar.AsyncState;
    Socket handler = state.workSocket;

    // Read data from the client socket. 
    int bytesRead = handler.EndReceive(ar);


    if (bytesRead > 0)
    {
        // There  might be more data, so store the data received so far.
        Buffer.BlockCopy(state.buffer, 0, _imageBuff, _totBytesRead, bytesRead);

        _totBytesRead += bytesRead;

        if (_totBytesRead < state.ImageSize)
        {
            // Not all data received. Get more.
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
            new AsyncCallback(ReadCallback), state);
        }
        else
        {
            File.WriteAllBytes(@"c:\temp\incoming\untitled.bmp", _imageBuff);
        }
    }
}
public static int Main(String[] args)
{
    StartListening();
    return 0;
}

客户端代码

void SendScreen()
{
HDC hdcScreen;
HDC hdcWindow;
HDC hdcMemDC = NULL;
HBITMAP hbmScreen = NULL;
BITMAP bmpScreen;

HWND hWnd = GetDesktopWindow();

// Retrieve the handle to a display device context for the client 
// area of the window. 
hdcScreen = GetDC(NULL);
hdcWindow = GetDC(hWnd);

// Create a compatible DC which is used in a BitBlt from the window DC
hdcMemDC = CreateCompatibleDC(hdcWindow); 

if(!hdcMemDC)
{
    //MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK);
    goto done;
}

// Get the client area for size calculation
RECT rcClient;
GetClientRect(hWnd,&rcClient);

//This is the best stretch mode
SetStretchBltMode(hdcWindow,HALFTONE);

//The source DC is the entire screen and the destination DC is the current 
window (HWND)
if(!StretchBlt(hdcWindow, 
           0,0, 
           rcClient.right, rcClient.bottom, 
           hdcScreen, 
           0,0,
           GetSystemMetrics (SM_CXSCREEN),
           GetSystemMetrics (SM_CYSCREEN),
           SRCCOPY))
    {
    MessageBox(hWnd, "StretchBlt has failed","Failed", MB_OK);
    goto done;
}

// Create a compatible bitmap from the Window DC
hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, 
rcClient.bottom-rcClient.top);

if(!hbmScreen)
{
    MessageBox(hWnd, "CreateCompatibleBitmap Failed","Failed", MB_OK);
    goto done;
}

// Select the compatible bitmap into the compatible memory DC.
SelectObject(hdcMemDC,hbmScreen);

// Bit block transfer into our compatible memory DC.
if(!BitBlt(hdcMemDC, 
           0,0, 
           rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, 
           hdcWindow, 
           0,0,
           SRCCOPY))
   {
    MessageBox(hWnd, "BitBlt has failed", "Failed", MB_OK);
    goto done;
   }

// Get the BITMAP from the HBITMAP
GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen);

BITMAPFILEHEADER   bmfHeader;    
BITMAPINFOHEADER   bi;

bi.biSize = sizeof(BITMAPINFOHEADER);    
bi.biWidth = bmpScreen.bmWidth;    
bi.biHeight = bmpScreen.bmHeight;  
bi.biPlanes = 1;    
bi.biBitCount = 32;    
bi.biCompression = BI_RGB;    
bi.biSizeImage = 0;  
bi.biXPelsPerMeter = 0;    
bi.biYPelsPerMeter = 0;    
bi.biClrUsed = 0;    
bi.biClrImportant = 0;

DWORD dwBmpSize = ((bmpScreen.bmWidth  bi.biBitCount + 31) / 32)  4 * 
bmpScreen.bmHeight;
HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize); 
char lpbitmap = (char )GlobalLock(hDIB);    
GetDIBits(hdcWindow, hbmScreen, 0,
    (UINT)bmpScreen.bmHeight,
    lpbitmap,
    (BITMAPINFO *)&bi, DIB_RGB_COLORS);
HANDLE hFile = CreateFile("capture.bmp",
    GENERIC_WRITE,
    0,
    NULL,
    CREATE_ALWAYS,
    FILE_ATTRIBUTE_NORMAL, NULL);   

// Add the size of the headers to the size of the bitmap to get the total file size
DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

//Offset to where the actual bitmap bits start.
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); 

//Size of the file
bmfHeader.bfSize = dwSizeofDIB; 

//bfType must always be BM for Bitmaps
bmfHeader.bfType = 0x4D42; //BM    


DWORD dwBytesWritten = 0;
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
SendingToSocketBFH(bmfHeader);
SendingToSocketBIH(bi);
SendingToSocket(lpbitmap,dwBmpSize);


//Unlock and Free the DIB from the heap
GlobalUnlock(hDIB);    
GlobalFree(hDIB);

//Close the handle for the file that was created
CloseHandle(hFile);

//Clean up
done:
DeleteObject(hbmScreen);
DeleteObject(hdcMemDC);
ReleaseDC(NULL,hdcScreen);
ReleaseDC(hWnd,hdcWindow);
}

void SendingToSocketBFH(BITMAPFILEHEADER bfinfo)
{
DWORD dwErr=0;
int sent=0;
sent = Send((char*)&bfinfo,sizeof(bfinfo),0);
dwErr = GetLastError();
}

void SendingToSocketBIH(BITMAPINFOHEADER binfo)
{
DWORD dwErr=0;
int sent=0;
sent = Send((char*)&binfo,sizeof(binfo),0);
dwErr = GetLastError();
}

void SendingToSocket(char* cpBuff,int iLen)
{
DWORD dwErr=0;
int sent=0;
sent = Send(cpBuff,iLen,0);
dwErr = GetLastError();
}

enter image description here enter image description here

0 个答案:

没有答案