我在两个 udp 客户端通过 udp 服务器(a->server->b)进行通信时遇到问题。首先,我将客户端的 address_in 保存到哈希图中,然后客户端 a 向客户端 b 发送一些消息。一切都是正确的(我记录了通信流程),除了服务器仅在使用客户端 b 的地址时向当前请求的客户端(客户端 a)发送消息。这是我的代码:
private:
std::map<int, sockaddr_in> ids_clients;
static int socket;
static void sig_handler(int signo) {
if (signo == SIGKILL) {
close(socket);
printf("stopped\n");
}
}
void monitor() {
int count;
socklen_t addr_size = sizeof (sockaddr_in);
struct sockaddr_in address;
std::map<int, sockaddr_in>::iterator client_it;
Buffer buffer;
Message message;
while (true) {
buffer.reset();
if ((count = recvfrom(socket, buffer.getBuffer(), buffer.getCapacity(), MSG_TRUNC, (struct sockaddr *) &address, &addr_size)) == -1) {
perror("network error!\n");
break;
}
if (count > message.getHeaderSize()) {
message.deserialize(&buffer, count);
int id = message.getTag();
printf("id: %d\n", id);
switch (message.getType()) {
case Message::Type::CONN:
{
//Save client address
printf("SOCK: %d, ID: %d, IP: %s, PORT: %d\n", socket, id, inet_ntoa(address.sin_addr), address.sin_port);
ids_clients[id] = address;
message.setTag(Message::Code::OK);
message.serialize(&buffer);
if (sendto(socket, buffer.getBuffer(), buffer.getSize(), 0, (struct sockaddr *) &address, addr_size) == -1) {
ids_clients.erase(ids_clients.find(id));
printf("Authenticated - client: %s:%d: could not response!\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
continue;
}
break;
}
case Message::Type::MEDIA:
{
//Send from current client to the client has id = message.getTag();
printf("SOCK: %d, ID: %d, IP: %s, PORT: %d\n", socket, id, inet_ntoa(address.sin_addr), address.sin_port);
if (message.getChannel() == Message::Channel::SINGLE) {
client_it = ids_clients.find(id);
if (client_it != ids_clients.end()) {
printf("ID: %d, IP: %s, PORT: %d\n", message.getSeqNo(), inet_ntoa(client_it->second.sin_addr), client_it->second.sin_port);
printf("SOCK: %d, SRC ID:%d, TO ID: %d\n", socket, message.getSeqNo(), id);
message.serialize(&buffer);
if (sendto(socket, buffer.getBuffer(), buffer.getSize(), 0, (struct sockaddr *) &(client_it->second), sizeof (client_it->second)) == -1) {
ids_clients.erase(client_it);
printf("Media package - client: %s:%d: could not reach!\n", inet_ntoa(client_it->second.sin_addr), ntohs(client_it->second.sin_port));
continue;
}
}
}
break;
}
}
} else {
//echo server
sendto(socket, buffer.getBuffer(), count, 0, (struct sockaddr *) &address, addr_size);
}
}
}
public:
void start(int port) {
signal(SIGKILL, sig_handler);
struct sockaddr_in sin;
socket = ::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int mps = PGK_MAX_SIZE;
if (setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &mps, sizeof (mps)) == -1) {
perror("SO_RCVBUF\n");
exit(EXIT_FAILURE);
}
memset(&sin, 0, sizeof (sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
if (bind(socket, (struct sockaddr *) &sin, sizeof (sin))) {
perror("bind()\n");
exit(EXIT_FAILURE);
}
printf("started: port %d\n", port);
monitor();
close(socket);
printf("stopped\n");
}
};
int Server::socket;
请帮忙,谢谢!