使用带有 GTK+ 的 GIOChannel 从发件人处获取 IP 地址

Get IP address from sender using GIOChannel with GTK+

我正在 raspberry pi 上使用 GTK+ 编写 C 程序。 有一个设备通过以太网端口连接到它(所有 UDP 通信)。 该设备向 pi 发送心跳,我可以接收到。 现在我需要将一些东西发送回设备。因此我需要知道它的 IP 地址。 我希望我的程序自动检测消息中的 IP 地址,但我不知道如何获取它。 这是设置套接字的代码:

  gd->gXctlServer = G_SOCKET_ADDRESS(g_inet_socket_address_new(g_inet_address_new_any(G_SOCKET_FAMILY_IPV4),XCTLPORT));
  gd->gXctlSocket = g_socket_new(G_SOCKET_FAMILY_IPV4,G_SOCKET_TYPE_DATAGRAM,G_SOCKET_PROTOCOL_UDP,&err);
  if (gd->gXctlSocket == NULL)
  {
    g_print("Error creating Xctl socket: %s\n",err->message);
    g_assert(err == NULL);
  }
  if (g_socket_bind(gd->gXctlSocket,gd->gXctlServer,TRUE,&err) == FALSE)
  {
    g_print("Error binding Xctl socket:%s\n",err->message);
    g_assert(err == NULL);
  }

  // add receiver watch for Xctl messages:
  gd->xctlChannel = g_io_channel_unix_new(g_socket_get_fd(gd->gXctlSocket));
  // set channel encoding to NULL for binary data:
  g_io_channel_set_encoding(gd->xctlChannel,NULL,&err);
  if (err != NULL) g_print("error setting encoding: %s\n",err->message);
  gd->xctlRrcvEvent = g_io_add_watch(gd->xctlChannel,G_IO_IN,(GIOFunc) xctlreceiver, NULL);
  g_io_channel_unref(gd->xctlChannel);

gd是指向一些全局数据的指针,其中server、socket和channel

这是我的监听器的代码:

// this function listens to all Xctl messages
static gboolean xctlreceiver(GIOChannel *channel, GIOCondition condition, gpointer data)
{
  char buf[1024];
  gsize read;
  GError *err = NULL;
  g_print("xctlreceiver\n");

  if (condition & G_IO_HUP) return FALSE;

  g_io_channel_read_chars(channel,buf,sizeof(buf),&read,&err);
  if (err != NULL) g_print("error receiving xctl: %s\n",err->message);
  g_print("received %d bytes\n",read);
  if (isXtouchHeartbeat(buf,read))
  {
    g_print("received heartbeat from X-touch\n");
  }
  return TRUE;
}

接收器正在工作,表示收到心跳。 但问题是:如何获取向我发送心跳的设备的 IP 地址。 有人可以帮我吗? 谢谢, 巴特
编辑:解决方案可能比我想象的要简单。 也许我不需要知道发件人的 IP 地址。如果我使用函数 g_io_channel_write_chars 并且使用与 g_io_channel_read_chars 函数相同的通道,它可能会起作用。
我会试试这个,稍后再回来。

我找到了解决问题的方法
我的接收函数现在看起来像这样:

static gboolean xctlreceiver(GIOChannel *channel, GIOCondition condition, gpointer data)
{
  char buf[1024];
  gsize read;
  GError *err = NULL;
  g_print("xctlreceiver\n");
  GSocketAddress *addr;

  if (condition & G_IO_HUP) return FALSE;

  if (gd->connectedToController == -1)
  {
    read = g_socket_receive_from(gd->gXctlSocket,&gd->gXctlController,buf,sizeof(buf),NULL,&err);    
    g_print("received %d bytes from XCTL socket on address %s\n",read,g_inet_address_to_string(g_inet_socket_address_get_address(G_INET_SOCKET_ADDRESS(gd->gXctlController))));
    for (int i=0; i<read; i++)
    {
      g_print("0x%02X ",buf[i]);
    }
    g_print("\n");
    if (isXtouchHeartbeat(buf,read))
    {
      g_print("received heartbeat from X-touch\n");
      gd->connectedToController = 1;
      sendXtouchHeartbeat(NULL);
      g_timeout_add_seconds(2,sendXtouchHeartbeat,NULL);

    }
  }
  else
  {
    g_io_channel_read_chars(channel,buf,sizeof(buf),&read,&err);
    if (err != NULL) g_print("error receiving xctl: %s\n",err->message);
    g_print("received %d bytes from XCTL channel\n",read);
    if (gd->connectedToController == -1)
    {
      //g_print("X-touch found on ip address: %s\n",inet_ntoa(si_recv.sin_addr));
      gd->connectedToController = 1;
    }

  }
  return TRUE;
}

函数g_socket_receive_from在第二个参数中给出了发件人的地址。
我把它放到我的 gd 结构中,以备后用。 希望这对遇到同样问题的人有所帮助。
氪,
巴特