0

UNIX ドメイン ソケット (ローカル ソケット) を介して通信する 2 つのデーモン (1 つのクライアントと 1 つのサーバー) があります。私が遭遇する問題は、関数 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));
4

1 に答える 1

0

エラーが見つかりました。サーバーコードでアドレス長グローバル変数のこの初期化を行う必要がありました。

//socklen_t address_length = 0;
socklen_t address_length = sizeof(myclient_address.sun_path);

address_length は、recvfrom 関数の値と結果の引数であるためです。

于 2015-09-07T08:50:10.370 に答える