none
Image processing from the client through TCP socket failed

    Question

  • I am developing an application for viewing client screen over TCP socket. my server application is in C# and the client application is in C++. I could send the image to the server without any error. At the server end, while converting buffer length I am getting a big number and this causes 'Overflow exception' while making image buffer with that size. Following are the code I have tried.

    Server Code:

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

    Client Code:

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


    • Edited by Jithu007 Wednesday, April 12, 2017 5:46 AM
    Wednesday, April 12, 2017 5:44 AM

All replies

  • Your code is unreadable because you pasted a code block within a code block. Please edit your post and fix the code. Also, this forum is for C#, not C++ so there is no reason to post that code. What you should instead do is post the code that you are using to read the data sent by the client. You should also post the format that you expect each message to be in. Generally this would be the message header containing information such as the length of the message and any pertinent commands. If you haven't defined a message header yet then that is likely the problem.

    Also keep in mind that network comms can fail at any time so you need to have some way of syncing messages back up. Given an arbitrary message of say 1234, there is no way to know where in the message header this resides if you don't have some sort of marker. Most headers tend to start with a well-define value such as 'MSG', 'HEADER', etc. Your code needs to include this error handling so you can recover from partially sent messages.

    Michael Taylor
    http://www.michaeltaylorp3.net

    Wednesday, April 12, 2017 2:02 PM
    Moderator