Передача изображения XImage по сети

Отладка останавливается на recvfrom();Пишу удаленный рабочий стол под Kali Linux. Подскажите пожалуйста, как правильно передать структуру XImage или само изображение с сервера клиенту, чтобы там корректно воспроизвети и отобразить. В моем случае в терминале клиента пишет: "Ошибка сегментирования". Сервер:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <cstdio>
#include <stdlib.h>
#include <unistd.h>

//------------------------------------------------------------------------------------------------
#define X 0
#define Y 0
#define WIDTH 600
#define HEIGHT 300
#define DISPLAY_WIDTH 1600
#define DISPLAY_HEIGHT 900
//------------------------------------------------------------------------------------------------
extern int errno;
//------------------------------------------------------------------------------------------------

int main()
{
    Display     *display;
    XImage      *image;

    int sock;
    struct sockaddr_in addr;

    // Соединяемся с X сервером
    if ((display = XOpenDisplay(getenv("DISPLAY"))) == NULL)
    {
        printf("Can't connect X server: %s\n", strerror(errno));
        exit(1);
    }

    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock < 0)
    {
        perror("socket");
        exit(1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425);
    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

    connect(sock, (struct sockaddr *)&addr, sizeof(addr));

    while(true){
        image = XGetImage(display, DefaultRootWindow(display), 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, AllPlanes, ZPixmap);
        send(sock, (char*)image, sizeof(image), 0);
        sleep(1);
    }
    close(sock);

    // Закрываем соединение с X сервером
    XCloseDisplay(display);

    return 0;
}

Клиент:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <cstdio>
#include <stdlib.h>
#include <unistd.h>

//------------------------------------------------------------------------------------------------
#define X 0
#define Y 0
#define WIDTH 600
#define HEIGHT 300
#define DISPLAY_WIDTH 1600
#define DISPLAY_HEIGHT 900
//------------------------------------------------------------------------------------------------
extern int errno;
//------------------------------------------------------------------------------------------------

int main()
{
    Display     *display;
    Window      window;
    XEvent      event;
    int         screen;
    XImage      *image = NULL;
    GC          graph_ctx;
    XGCValues   *gc_values;

    // Соединяемся с X сервером
    if ((display = XOpenDisplay(getenv("DISPLAY"))) == NULL)
    {
        printf("Can't connect X server: %s\n", strerror(errno));
        exit(1);
    }
    screen = XDefaultScreen(display);
    //image = XGetImage(display, DefaultRootWindow(display), 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, AllPlanes, ZPixmap);

    // Создаем окно
    window = XCreateSimpleWindow(display, RootWindow(display, screen), X, Y, WIDTH, HEIGHT, 10, XBlackPixel(display, screen), XWhitePixel(display, screen));
    // Создаем графический контекст
    graph_ctx=XCreateGC(display, window, 0, gc_values);
    // На какие события будем реагировать
    XSelectInput(display, window, ExposureMask | KeyPressMask);
    //Показываем окно на экране
    XMapWindow(display, window);

    int sock;
    struct sockaddr_in addr;
    int bytes_read;

    sock = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock < 0)
    {
        perror("socket");
        exit(0);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        exit(1);
    }

    char buf[sizeof(image->data)];
    while(1)
    {
        recvfrom(sock, (XImage*)image, sizeof(image), 0, NULL, NULL);
        // Отображаем картинку в окне
        XPutImage(display, window, graph_ctx, image, 0, 0, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
    }
    close(sock);
    // Закрываем соединение с X сервером
    XCloseDisplay(display);
    return 0;
}


Ответы (2 шт):

Автор решения: KoVadim

В коде такое кол-во ошибок, что даже сложно что то предположить одно. Начнем с базы. Мне кажется, что код сервера и клиента немного "перепутан".

В коде есть фундаментальная ошибка. Даже не ошибка, а ОШИБИЩЕ. Подумайте, какой размер sizeof(image) - скорее всего он 8 (или 4, если Вы случайно нашли 32 битную версию). Поэтому, Вы передаете не картинку, а просто указатель на нее. А с него толку мало на другой машине. Но даже если код поправить, я не знаю, можно ли просто так взять и передать XImage. Тут нужно аккуратно написать свой сериализатор/десириализатор. То есть, нужно подумать, как картинку преобразовать в набор байт и обратно. Скорее всего придется пробежаться построчно и пиксель за пикселем скопировать. Но если верить этому - https://tronche.com/gui/x/xlib/graphics/images.html - то все может получится.

В коде еще есть вагон ошибок, но их исправлять - это с нуля новое написать.

→ Ссылка
Автор решения: sever7788

Нужно было отправлять только массив данных изображения: send(sock, image->data, width*height*4, 0); И соответствующе принимать.

→ Ссылка