Как управлять исходящим портом при отправке сообщения через TCP-соединение с GSocket?

Я использую C, Linux и GIO GSocket для создания небольшого приложения для связи с цифровым проектором через TCP. Разъем успешно подключен, и я могу успешно отправлять сообщения на проектор. Моя проблема заключается в том, что я не могу получать сообщения автоматического подтверждения, возвращаемые проектором при получении команды. Когда я отправляю сообщение, затем использую g_socket_receive, он блокируется и, кажется, никогда не получает ответ.

Мое подозрение на проблему, основанное на прошлых подобных проблемах на других языках, заключается в том, что когда я отправляю сообщение с помощью g_socket_send, сообщение отправляется на произвольно доступный локальный порт. Затем проектор автоматически ответит на порт, с которого отправлено сообщение. Не зная, какой порт он использовал, я не могу заставить мой GSocket прослушивать правильный порт. На других языках было просто установить вручную мой локальный исходящий порт, чтобы я знал, куда будет возвращаться ответ. Однако я не смог найти никакой информации о том, как это сделать с GSocket.

Может кто-нибудь предложить какую-либо помощь в этом, или какие-либо мысли о том, что еще проблема может быть, что я скучаю?

Спасибо!

2 ответа

Решение

Ваш вызов на чтение / прием, скорее всего, блокируется, потому что вы заказываете, чтобы прочитать / получить больше байтов, чем отправленный ответ, длинный.

Для целей тестирования сделайте что-то вроде этого:

int fd = -1;
/* setup fd */
char buffer[1024] = {0};
ssize_t size_buffer = sizeof(buffer) - 1;
size_t size_read_total = 0;
ssize_t size_read = 0;

while (size_buffer > size_read_total)
{
  size_read = read(fd, buffer + size_read_total, 1); /* Wait until exactly one byte had been read. */
  if (-1 = size_read)
  {
    if (EINTR == errno)
    {
      continue;
    }

    if ((EAGAIN == errno) || (EWOULDBLOCK == errno))
    {
      continue;
    }

    break;  /* Fatal error */
  }
  else (0 == size_read)
  {
    break; /* Connection closed by sending side. */
  }

  size_read_total += size_read;
} 

if (-1 == size_read)
{
  perror("read() failed");
}
else
{
  printf("Received %zd bytes as: '%s'\n", size_read_total, buffer);
}

Вы можете связать исходящий GSocket на локальный адрес (IP и порт) с g_socket_bind функция, как вы делаете для прослушивания сокетов.

Это вряд ли решит вашу проблему. Проектор должен отправить ответные пакеты на порт, с которого был отправлен запрос; очень редко вам нужно привязать клиентский сокет к определенному порту. Проверьте, что отправлено и получено с wireshark или же tcpdump,

Другие вопросы по тегам