关于位图传输之后显示的问题

如题,我把位图放到char*中,然后通过socket传输,传输没有问题,但是在服务端显示之后,界面会跳动。

测试截图如下:

第一张:正常情况

 

第二张图:

 

第二张图最显眼的地方就是任务栏位置,这是我下断点调试出来的图像,如果连续的话,整个图像看上去就是向左移动的图像,在客户端自己显示是没有问题的,能够实时捕捉屏幕影像。想问下怎么造成的,有什么解决方法嘛?

下面是我的服务段接受并显示的代码:

HDC hdc = BeginPaint(hWnd, &ps);
		HDC screen = GetDC(hWnd);
		RECT rcClient;
		GetClientRect(hWnd, &rcClient);
		HDC mdc = CreateCompatibleDC(screen);
		HBITMAP MyBit = ::CreateCompatibleBitmap(screen, WindowrcClient.right, WindowrcClient.bottom);
		SelectObject(mdc, MyBit);
		LONG s = 0;
		aa = pBits.size();
		s = SetBitmapBits(MyBit, pBits.size(), pBits.data());
		qDebug() << s;
		pBits.clear();
		SetStretchBltMode(screen, HALFTONE);
		StretchBlt(screen,
			0, 0,
			rcClient.right, rcClient.bottom,
			mdc,
			0, 0,
			GetSystemMetrics(SM_CXSCREEN),
			GetSystemMetrics(SM_CYSCREEN),
			SRCCOPY);	

能够完全接收位图数据。

如果在数据传输过程中出现了将图片从中间切开并左右互换的问题,可能是由于数据传输过程中的拆包和粘包问题导致的。

TCP是一种面向流的传输协议,在发送端发送的数据可能会被拆分成多个数据包进行传输,而在接收端接收到的数据可能会出现粘连,多个数据包粘在一起的情况。这可能导致接收端解析数据时发生错位,造成图片被切开并左右互换的问题。

为了解决这个问题,可以在传输过程中引入消息边界或长度信息来正确地解析数据。以下是一种可能的解决方案:

1、发送端:在发送端,在发送位图数据之前,先将位图的长度信息发送给接收端。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

void sendBitmapViaSocket(const char* bitmapData, int dataSize, const char* ipAddress, int port) {
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        printf("Failed to create socket\n");
        return;
    }

    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(port);
    serverAddr.sin_addr.s_addr = inet_addr(ipAddress);

    if (connect(sockfd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
        printf("Failed to connect to server\n");
        close(sockfd);
        return;
    }

    // 发送位图长度信息
    int dataSizeNetworkOrder = htonl(dataSize);
    send(sockfd, &dataSizeNetworkOrder, sizeof(dataSizeNetworkOrder), 0);

    // 发送位图数据
    send(sockfd, bitmapData, dataSize, 0);

    close(sockfd);
}


2、接收端:在接收端,先接收位图的长度信息,然后根据长度信息接收相应大小的位图数据。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

void receiveBitmapViaSocket(const char* filename, int sockfd) {
    // 接收位图长度信息
    int dataSizeNetworkOrder;
    recv(sockfd, &dataSizeNetworkOrder, sizeof(dataSizeNetworkOrder), 0);
    int dataSize = ntohl(dataSizeNetworkOrder);

    // 接收位图数据
    char* bitmapData = (char*)malloc(dataSize);
    int bytesRead = 0;
    while (bytesRead < dataSize) {
        int received = recv(sockfd, bitmapData + bytesRead, dataSize - bytesRead, 0);
        if (received < 0) {
            printf("Failed to receive bitmap data\n");
            break;
        }
        bytesRead += received;
    }

    // 将位图数据写入文件
    FILE* file = fopen(filename, "wb");
    if (file != NULL) {
        fwrite(bitmapData, 1, dataSize, file);
        fclose(file);
    }

    free(bitmapData);
}


通过在数据传输过程中包含长度信息,可以确保接收端能够正确地解析位图数据,并避免数据粘连和错位的问题。在发送端发送位图数据之前,将位图的长度信息发送给接收端,然后接收端先接收长度信息,再根据长度信息接收相应大小的位图数据,最后将位图数据写入文件。

请注意,以上代码仅是一种可能的解决方案,具体实现方式可能因实际需求和环境而有所不同。在实际使用时,你可以根据具体情况进行调整和优化。