【问题标题】:How to find server on LAN with sockets (UDP) in C++如何在 C++ 中使用套接字 (UDP) 在 LAN 上查找服务器
【发布时间】:2019-11-27 11:47:03
【问题描述】:

各位程序员大家好!我正在用 C++ 编写一个程序,该程序应该允许使用 Windows 套接字通过 LAN 在两台计算机之间进行实时数据传输。由于数据应该尽可能快地传输,我使用 UDP(这是一个游戏,因此只有最新的数据是相关的)。现在,由于我在单机上对其进行了测试,因此我使用以下代码将服务器 IP 分配给客户端

SOCKADDR_IN server_address;
server_address.sin_family = AF_INET;
server_address.sin_port = htons(PORT);
server_address.sin_addr.S_un.S_un_b.s_b1 = 127;
server_address.sin_addr.S_un.S_un_b.s_b2 = 0;
server_address.sin_addr.S_un.S_un_b.s_b3 = 0;
server_address.sin_addr.S_un.S_un_b.s_b4 = 1;

现在,我需要它在 LAN 中运行,服务器和客户端的确切地址可能未知。在这种情况下如何连接?如果我广播到255.255.255.255就够了吗?或者也许还有另一种与两台计算机握手的方式?

【问题讨论】:

  • 您可以有一个单独的广播阶段,客户端将广播发送到网络。服务器监视这些并使用自己的地址进行回复。一个限制是广播可能不会在具有相同网络掩码的网络段之间传递。为了克服这个问题,您可以在固定且众所周知的地址上拥有一个目录服务器,客户端可以连接并获取已知服务器的列表。或者只需让用户在每个会话中输入服务器的地址。
  • 嗯,你当然可以向广播IP地址发送数据报。然后希望只有一个IP地址响应。如果你收到两个回复怎么办?还是四个?我们的42?你打算下一步做什么?如果您打算只处理对广播的第一个响应,您如何确保您的预期 IP 地址始终首先响应?
  • 您可能希望了解使用 IP 多播通告/发现机制,例如 avahi
  • 我只回复第一个广播就够了。另外,我想我可以发送 1 个数据包,其中包含服务器和客户端都将拥有的数字,如果数字不匹配,我可以断开套接字。
  • 两个不同的人可以同时玩两个不同的游戏吗?

标签: c++ sockets udp connection


【解决方案1】:

好的,我完成了我的项目,所以我将借此机会展示我用于查找服务器的代码。正如建议的那样,它基于在客户端广播并发送回数据报,将服务器的IP提供给客户端,稍后用于提供定向通信。

服务器:

bool handshakeS()
{
    SOCKET sockhs;
    sockhs = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    char broadcast = '1';
    if (setsockopt(sockhs, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0)
    {
        closesocket(sockhs);
        return false;
    }

    struct sockaddr_in Recv_addr;
    struct sockaddr_in Sender_addr;

    int len = sizeof(struct sockaddr_in);

    char recvbuff[1];
    int recvbufflen = 1;
    char sendMSG[] = "";

    Recv_addr.sin_family = AF_INET;
    Recv_addr.sin_port = htons(PORTHS);
    Recv_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sockhs, (sockaddr*)&Recv_addr, sizeof(Recv_addr)) < 0)
    {
        closesocket(sockhs);
        return false;
    }
    recvfrom(sockhs, recvbuff, recvbufflen, 0, (sockaddr*)&Sender_addr, &len);

    if (sendto(sockhs, sendMSG, strlen(sendMSG) + 1, 0, (sockaddr*)&Sender_addr, sizeof(Sender_addr)) < 0)
    {
        closesocket(sockhs);
        return false;
    }
    return true;
    closesocket(sockhs);
}

客户:

bool handshakeC(int& ip1temp, int& ip2temp, int& ip3temp, int& ip4temp)
{
    SOCKET sockhs;
    sockhs = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    char broadcast = '1';
    if (setsockopt(sockhs, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0)
    {
        closesocket(sockhs);
        return false;
    }

    struct sockaddr_in Recv_addr;
    struct sockaddr_in Sender_addr;

    int len = sizeof(struct sockaddr_in);

    char sendMSG[] = ""; //may be used for authorization
    char recvbuff[1] = "";
    int recvbufflen = 1;

    Recv_addr.sin_family = AF_INET;
    Recv_addr.sin_port = htons(PORTHS);
    Recv_addr.sin_addr.s_addr = INADDR_BROADCAST;

    sendto(sockhs, sendMSG, strlen(sendMSG) + 1, 0, (sockaddr*)&Recv_addr, sizeof(Recv_addr));
    recvfrom(sockhs, recvbuff, recvbufflen, 0, (sockaddr*)&Recv_addr, &len);

    ip1temp = Recv_addr.sin_addr.S_un.S_un_b.s_b1;
    ip2temp = Recv_addr.sin_addr.S_un.S_un_b.s_b2;
    ip3temp = Recv_addr.sin_addr.S_un.S_un_b.s_b3;
    ip4temp = Recv_addr.sin_addr.S_un.S_un_b.s_b4;
    closesocket(sockhs);
    return true;
}

【讨论】:

    猜你喜欢
    • 2012-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2017-10-03
    • 2012-07-22
    相关资源
    最近更新 更多