Привет, мой вопрос прост:
Я пытаюсь установить соединение UDP через соединение TCP (поскольку несколько клиентов подключены к серверу через несколько каналов, и я хочу идентифицировать тех же клиентов через основное соединение TCP)
Я сделал это, создав на клиенте сокет TCP и UDP и передав на сервер локальный порт UDP, назначенный операционной системой случайным образом через TCP. (В Windows я получаю порт после sendto () через getsocketname ()).
На сервере я использую этот порт для отправки UDP-пакетов именно этому клиенту.
К сожалению, порт, который мне действительно нужно отправить, отличается от локального порта, который я отправил на сервер.
Например:
Мой клиент получает локальный UDP-порт 56423. Отправляет его на мой сервер через установленное TCP-соединение. Сервер пытается отправить UDP-пакеты на этот порт -> Failed.
Когда я использую стандартный способ получения порта на сервере через recv () на сокете UDP, он сообщает об исходном порте 30299. (Я должен заранее отправить UDP-пакеты для этой информации, но я хочу избежать реализации UDP рукопожатие соединения)
Как это может быть?
Насколько я понимаю, UDP просто имеет порт назначения и порт источника. Так что должно работать, отправляя клиенту локальный порт на сервер.
Могут ли быть прокси-сервисы между ними, использующие альтернативные порты?
Редактировать:
Некоторый код:
На клиенте:
(s32 = int, c8 = char)
if(m_WinSock == INVALID_SOCKET)
return;
struct sockaddr_storage addr;
s32 len = sizeof(sockaddr);
getsockname(m_WinSock, (SOCKADDR*)&addr, &len);
c8 ipstr[INET6_ADDRSTRLEN + 1];
s32 port;
if(addr.ss_family == AF_INET)
{
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
m_uLocalPort = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
}
else
{ // AF_INET6
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
m_uLocalPort = ntohs(s->sin6_port);
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
}
m_uLocalPort передается через TCP после этого.
На сервере:
SOCKADDR_IN address;
ZeroMemory(&address, sizeof(address));
address.sin_addr = addrin;
address.sin_port = htons((u16)remoteport);
address.sin_family = AF_INET;
remoteport — это порт, отправленный клиентом.
Используя этот код на сервере после отправки пакета от клиента:
struct sockaddr_storage addr;
s32 len = sizeof(sockaddr);
s32 bytes = recvfrom(m_WinSock, m_RecvBuffer, NET_MAX_UDP_SIZE, 0, (SOCKADDR*)&addr, &len);
m_RecvAddress = *(struct sockaddr_in *)&addr;
s32 port = ntohs(m_RecvAddress.sin_port);
printf("recv from port %i\n", port);
Я получаю совершенно другой порт.
Это не надежный подход к проблеме. Например, NAT может мешать и переназначать ваш порт или даже локальный IP-адрес, видимый от вашего клиента. Вам также может понадобиться сделать пробивание дырок в UDP.
Правильный путь не предполагает никакой взаимосвязи между tcp и udp — это разные каналы.
РЕДАКТИРОВАТЬ: Например:
connect()
к общедоступному TCP-интерфейсу сервера.sendto()
общедоступный интерфейс udp сервера, с cookie.sockaddr
от recvfrom()
,sockaddr
на подключение к TCP, используя cookie. При желании проверьте / ограничьте IP-адрес, чтобы предотвратить использование силы быка другими.sockaddr
для связи udp.PS. Вы можете также захотеть сделать некоторое шифрование на рукопожатии, но это выходит за рамки вопроса.