Передача изображения XImage по сети
Пишу удаленный рабочий стол под 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 шт):
В коде такое кол-во ошибок, что даже сложно что то предположить одно. Начнем с базы. Мне кажется, что код сервера и клиента немного "перепутан".
В коде есть фундаментальная ошибка. Даже не ошибка, а ОШИБИЩЕ. Подумайте, какой размер sizeof(image) - скорее всего он 8 (или 4, если Вы случайно нашли 32 битную версию). Поэтому, Вы передаете не картинку, а просто указатель на нее. А с него толку мало на другой машине. Но даже если код поправить, я не знаю, можно ли просто так взять и передать XImage. Тут нужно аккуратно написать свой сериализатор/десириализатор. То есть, нужно подумать, как картинку преобразовать в набор байт и обратно. Скорее всего придется пробежаться построчно и пиксель за пикселем скопировать. Но если верить этому - https://tronche.com/gui/x/xlib/graphics/images.html - то все может получится.
В коде еще есть вагон ошибок, но их исправлять - это с нуля новое написать.
Нужно было отправлять только массив данных изображения: send(sock, image->data, width*height*4, 0); И соответствующе принимать.