Обзор
Я пишу простой тестовый игровой сервер на C ++. В настоящее время у меня есть связанный сокет, который слушает кого-либо, и когда приходит определенный тип пакета, я хочу сохранить структуру sockaddr в объект, который будет передан в отдельный поток. Этот отдельный поток будет перебирать все сокеты и пытаться записать в них данные.
В целях тестирования я просто хочу сделать следующее:
- Прослушивание пакета и определение его типа (сделано)
- Передача информации об адресе источника в отдельную функцию (выполнено)
- Создайте новый сокет и привяжите его к новому порту (готово, но, возможно, проблема здесь?)
- Отправка данных через этот вновь связанный / сделанный сокет с использованием sockaddr_in, который был передан ранее (сделано?)
Настройка
Прием
В настоящее время настроен глобальный слушатель:
void lobbyactions_thread() {
struct sockaddr_in any;
memset(&any, 0, sizeof(any));
any.sin_family = AF_INET;
any.sin_port = htons(LOBBYACTIONS_PORT);
any.sin_addr.s_addr = htonl(INADDR_ANY);
unsigned int any_sz = sizeof(any);
packets::LOBBYACTION_PACKET jpacket;
int socketfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
bind(socketfd, (struct sockaddr*) &any, sizeof(any))
while (server_manager::STAY_ALIVE) {
struct sockaddr_in* new_con = new struct sockaddr_in;
memset(new_con, 0, sizeof(*new_con));
unsigned int new_con_size = sizeof(*new_con);
recvfrom(socketfd, &jpacket, packets::LOBBYACTION_PACKET_SIZE, 0, (sockaddr*)new_con, &new_con_size);
bool save = false;
if (jpacket.type == JOIN) { save = true; server_manager::join(jpacket.id, new_con); }
// ...
jpacket.okay = true;
if (!save) {
sendto(socketfd, &jpacket, packets::LOBBYACTION_PACKET_SIZE, 0, (sockaddr*)&any, any_sz);
free(any);
}
}
}
Сохранение и временная отправка
Когда соединение обрабатывается, я хочу сохранить получателя во внутренней очереди других получателей / пользователей / соединений. Для тестирования у меня есть этот метод соединения, который просто создаст новый сокет, свяжет его и отправит некоторые данные в качестве подтверждения концепции.
struct Slot {
int playerSocket;
int playerAssignedPort;
struct sockaddr_in* sourceAddress;
unsigned int sourceAddressSize;
};
void join(int id, struct sockaddr_in* raddr) {
Slot* ps = new Slot();
ps->playerAssignedPort = 8810 // temporary
ps->playerSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(ps->playerAssignedPort);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
ps->sourceAddressSize = sizeof(addr);
bind(ps->playerSocket, (struct sockaddr*)&addr, ps->sourceAddressSize);
ps->sourceAddress = raddr;
ps->sourceAddress->sin_port = htons(ps->playerAssignedPort);
// ...
sendto(ps->playerSocket, &updatePacket, packets::GAMESTATE_PACKET_SIZE, 0, (sockaddr*)(ps->sourceAddress), ps->sourceAddressSize);
// ...
}
Вопрос
Почему я не могу привязаться к этому сокету? Я пропускаю не тот раздел any
? Или это то, что на самом деле невозможно? Любая помощь или указатели (возможно, это был бы ужасный каламбур) были бы великолепны.
Почему при сохранении struct sockaddr_in, заполненной recvfrom
, я по какой-то причине больше не могу отправлять сообщения, хотя и через другой порт и другой сокет? Как ни странно, я пришел к выводу, что , когда клиент и сервер должны проходить через локальный маршрутизатор, это не работает, но если клиент и сервер не должны проходить через локальный маршрутизатор, этот факт работает ! Может быть, мне нужна дополнительная информация о пакете / заголовке? Или маршрутизатор делает что-то (или его отсутствие), что ограничит сообщения? Может ли быть так, что есть какая-то странная проблема с переадресацией портов, которая не влияет на проблему с программным обеспечением при игре здесь?
Редактировать
Может быть важно отметить, что все работает в настоящее время в методе lobbyactions_thread()
, то есть получать, обрабатывать и отправлять. Проблема заключается в методе join()
.
Обновленный код, частично из собственного открытия и User @ selbie