我在 :: 上啟動服務器以接受所有可能的連接。
void StartServer(std::string ip, unsigned int port)
{
union sockaddr_types
{
struct sockaddr_storage storage;
struct sockaddr addr;
struct sockaddr_in in4;
struct sockaddr_in6 in6;
};
sockaddr_types address_storage = {};
if (inet_pton(PF_INET, ip.c_str(), &address_storage.in4.sin_addr) == 1)
{
address_storage.in4.sin_family = AF_INET;
address_storage.in4.sin_port = htons(port);
}
else if (inet_pton(PF_INET6, ip.c_str(), &address_storage.in6.sin6_addr) == 1)
{
address_storage.in6.sin6_family = AF_INET6;
address_storage.in6.sin6_port = htons(port);
}
else
{
return;
}
SocketFd = socket(address_storage.addr.sa_family, SOCK_STREAM, 0); // SocketFd a class member or a global variable
int opt = 1;
int ret = 0;
if (setsockopt(SocketFd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
{
// Error
}
else
{
if ((ret = bind(SocketFd, &address_storage.addr, sizeof(address_storage))) < 0)
{
// Error
}
else
{
if ((ret = listen(SocketFd, QueueSize)) < 0)
{
// Error
}
else
{
while (true) // Just to simplify example
{
int clientScoketFd = 0;
sockaddr_in clientAddr = {};
socklen_t clientAddrlen = sizeof(clientAddr);
if ((clientScoketFd = accept(SocketFd, (sockaddr *)&clientAddr, &clientAddrlen)) < 0)
{
// Error
}
char buff[255] = {};
inet_ntop(clientAddr.sin_family, &clientAddr.sin_addr, buff, sizeof(buff));
printf("IP %s\n", buff);
DoJobOnSocket(clientScoketFd, buff);
}
}
}
}
}
使用 IPv4 的客戶端連接到服務器后,輸出為
"IP ::"
為什么它是零而不是 IPv4?當我開始使用 IPv4 地址時,它作業正常,我看到客戶端的 IPv4。有沒有辦法在這種情況下在這里獲取 IPv4,或者我必須在 IPv4 地址上啟動服務器?
uj5u.com熱心網友回復:
客戶端可能使用 IPv6 而不是通過 IPv4 連接到服務器。您應該檢查地址系列(sin_family在您的情況下)。如果那樣的AF_INET話,那inet_ntop將永遠不會回來::。
僅檢查sin_family成員是相對安全的,但檢查sin_addr地址是否可能是 IPv6 地址不是。您應該使用 astruct sockaddr_storage來存盤地址,但將其轉換為 astruct sockaddr并僅使用該sa_family成員,直到您知道它是哪種型別的地址。然后你可以將它轉換為struct sockaddr_inor struct sockaddr_in6。
該getnameinfo函式很好地處理了這個問題。它會自動完成所有這些作業。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/488793.html
上一篇:如何使用多條曲線添加懸停注釋
