У меня есть два демона (один клиент и один сервер), которые общаются через сокеты домена unix (локальные сокеты). Проблема, с которой я сталкиваюсь, заключается в том, что при первом приеме дейтаграммы сервером с помощью функции recvfrom адрес клиента, предоставленный функцией recvfrom, оказывается пустым. Однако размер предоставленного адреса клиента кажется правильным. Если я увеличу длину адреса (более длинное имя) в клиентском демоне, это отразится на увеличении размера адреса на сервере. Также полученные данные верны.
Обратите внимание, что эта проблема возникает только при первом получении дейтаграммы на сервере. Когда другие дейтаграммы получены, поле адреса правильное.
Есть тут специалисты, которые понимают, что может быть не так?
Код сервера:
static struct sockaddr_un myclient_address;
socklen_t address_length = 0;
int fd;
struct sockaddr_un addr;
struct my_device *dev = dev->device;
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
f_warning("socket error");
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
memset(&myclient_address, 0, sizeof(myclient_address));
myclient_address.sun_family = AF_UNIX;
char *socket_path = "#myserver";
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
addr.sun_path[0] = '\0';
unlink(socket_path);
if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
f_warning("bind error");
}
dev->socket_fd = fd;
dev->socket_io_channel = g_io_channel_unix_new(fd);
dev->socket_io_src_id = g_io_add_watch(dev->socket_io_channel,
G_IO_IN,
socket_in_data_callback,
dev);
static gboolean
socket_in_data_callback(GIOChannel *source, GIOCondition cond, gpointer data)
{
struct my_device *dev = data;
gsize read_count = 0;
GIOStatus status;
guchar* data = g_malloc0(300);
read_count = recvfrom(dev->socket_fd, (char *) data, 300, 0,
(struct sockaddr *) &(myclient_address), &address_length);
return TRUE;
}
Код клиента:
int fd;
struct sockaddr_un mycli_addr;
fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (fd < 0) {
f_warning("socket error");
}
memset(&addr, 0, sizeof(addr));
memset(&mycli_addr, 0, sizeof(mycli_addr));
addr.sun_family = AF_UNIX;
mycli_addr.sun_family = AF_UNIX;
char *socket_path = "#myserver";
char *mycli_socket_path = "#myclient";
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path));
strncpy(mycli_addr.sun_path, mycli_socket_path, sizeof(mycli_addr.sun_path));
addr.sun_path[0] = '\0';
mycli_addr.sun_path[0] = '\0';
unlink(socket_path);
unlink(mycli_socket_path);
int er;
er = bind(fd, (struct sockaddr*)&mycli_addr, sizeof(mycli_addr));
if (er < 0) {
f_warning("bind error");
}
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
f_warning("connect error");
}
session->socket_io_channel = g_io_channel_unix_new(fd);
session->socket_io_src_id = g_io_add_watch(session->socket_io_channel,
G_IO_IN,
client_socket_in_data_callback,
session);
sendto(session->socket, (char *) mydata, data_length, 0,
(struct sockaddr *) &addr,
sizeof(struct sockaddr_un));