我已经用C++创建了服务器和客户端,我希望它们在同一网络上但在不同计算机上运行时相互连接。我当前正在使用以下代码来使服务器连接到网络:

#define HOST_PORT "27015"

WSADATA wsaData;
int status;
struct addrinfo * data;
struct addrinfo hints;

WSAStartup(MAKEWORD(2, 2), &wsaData);

ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_IP;
hints.ai_flags = AI_PASSIVE;

char hostname[1024];
hostname[1023] = '\0';
gethostname(hostname, 1023);

if (getaddrinfo(hostname, HOST_PORT, &hints, &data))
{
    std::cout << "Unable to translate host name to address\n";
    WSACleanup();

    return 1;
}

客户端尝试使用类似的代码进行连接:
#define DEFAULT_PORT "27015"

struct addrinfo hints;

ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

char hostname[1024];
hostname[1023] = '\0';
gethostname(hostname, 1023);

struct addrinfo *result = NULL;
int iResult = getaddrinfo(hostname, DEFAULT_PORT, &hints, &result);

if (iResult != 0)
{
    std::cout << ("getaddrinfo failed with error: %d\n", iResult);
    WSACleanup();

    return false;
}

当客户端和服务器位于同一台计算机上时,这可以很好地工作,但是当它们位于不同的计算机上时,如何允许它们连接?我希望在使用gettaddrinfo()时需要客户端连接到相同的主机名,但是如何获得服务器的主机名? (例如,如果服务器上的hostname变为“InsertNameHere”,如何允许客户端检测“InsertNameHere”并将其用作getaddrinfo()中的第一个参数?)

最佳答案

您的问题相当普遍,有几种解决方法。

手动配置

例如,您的服务器可能会找到它的IP4地址,将其打印到控制台,然后以某种方式在客户端应用中手动指定该地址,例如作为命令行参数或在某些配置文件中。

这是对开发人员最友好,最不友好的方式。

服务发布

您的服务器可能会在启动时自行注册到客户端可以读取的位置。人们通常在Active Directory就是“某个地方”的企业Windows环境中实现此方法。如果是这种情况,请为您需要的WinSock API使用see this article

服务发现

或者,您可以自己实现发现机制,例如使用UDP广播。

在您的服务器中,监听某些UDP端口,等待一些发现数据报,然后响应一些“发现的OK”数据报。

在客户端中,在启动时,将发现UDP数据报发送到该UDP端口号的广播地址。如果您的服务器在与客户端相同的子网上运行,则客户端将收到“发现成功”消息。如果只有一个响应,则说明只有一台可访问的服务器,您可以立即连接。如果有多个响应,则可能意味着有多个服务器,您可以询问用户连接位置。

这种方法很难正确实现(例如UDP无法保证传送,因此需要重试和超时),但这是最用户友好的方法。如果您曾经玩过Quake之类的旧LAN游戏,那么它们就是找到服务器的方式。

我想补充一下,您可以使用第三方库,例如CollageReplicaNet,但是我对这些都没有实际经验,因此不能推荐其中任何一个。

关于c++ - 如何获取服务器的主机名?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34343108/

10-11 22:43
查看更多