我已经用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游戏,那么它们就是找到服务器的方式。
我想补充一下,您可以使用第三方库,例如Collage和ReplicaNet,但是我对这些都没有实际经验,因此不能推荐其中任何一个。
关于c++ - 如何获取服务器的主机名?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34343108/