Winsock 错误 10049 尝试绑定

winsock error 10049 trying to bind

本文关键字:绑定 10049 错误 Winsock      更新时间:2023-10-16

我的服务器连接有问题。当我尝试将服务器绑定到我的外部设备 IP 时,我收到一个 winsock 错误:10049 无法分配请求的地址。使用本地主机服务器可以正常工作。此 IP 地址:192.168.0.202 ping 成功。我在win8.1上工作。我关闭了防火墙和窗口防御器,它没有帮助。

带有服务器实现的代码取自 http://www.planetchili.net/forum/viewtopic.php?f=3&t=3433

#include "Server.h"
Server::Server(int PORT, bool BroadcastPublically) //Port = port to broadcast on. BroadcastPublically = false if server is not open to the public (people outside of your router), true = server is open to everyone (assumes that the port is properly forwarded on router settings)
{
    //Winsock Startup
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0) //If WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
    {
        MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);
        exit(1);
    }

    addr.sin_addr.s_addr = inet_addr("192.168.0.202"); 
    addr.sin_port = htons(1234); //Port
    addr.sin_family = AF_INET; //IPv4 Socket
    sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
    if (bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) //Bind the address to the socket, if we fail to bind the address..
    {
        std::string ErrorMsg = "Failed to bind the address to our listening socket. Winsock Error:" + std::to_string(WSAGetLastError());
        MessageBoxA(NULL, ErrorMsg.c_str(), "Error", MB_OK | MB_ICONERROR);
        exit(1);
    }
    if (listen(sListen, SOMAXCONN) == SOCKET_ERROR) //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max Connections, if we fail to listen on listening socket...
    {
        std::string ErrorMsg = "Failed to listen on listening socket. Winsock Error:" + std::to_string(WSAGetLastError());
        MessageBoxA(NULL, ErrorMsg.c_str(), "Error", MB_OK | MB_ICONERROR);
        exit(1);
    }
    serverptr = this;
}
bool Server::ListenForNewConnection()
{
    SOCKET newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
    if (newConnection == 0) //If accepting the client connection failed
    {
        std::cout << "Failed to accept the client's connection." << std::endl;
        return false;
    }
    else //If client connection properly accepted
    {
        std::cout << "Client Connected! ID:" << TotalConnections << std::endl;
        Connections[TotalConnections] = newConnection; //Set socket in array to be the newest connection before creating the thread to handle this client's socket.
        CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(TotalConnections), NULL, NULL); //Create Thread to handle this client. The index in the socket array for this thread is the value (i).
        //std::string MOTD = "MOTD: Welcome! This is the message of the day!.";
        //SendString(TotalConnections, MOTD);
        TotalConnections += 1; //Incremenent total # of clients that have connected
        return true;
    }
}
bool Server::ProcessPacket(int ID, Packet _packettype)
{
    switch (_packettype)
    {
    case P_ChatMessage: //Packet Type: chat message
    {
        std::string Message; //string to store our message we received
        if (!GetString(ID, Message)) //Get the chat message and store it in variable: Message
            return false; //If we do not properly get the chat message, return false
                          //Next we need to send the message out to each user
        for (int i = 0; i < TotalConnections; i++)
        {
            if (i == ID) //If connection is the user who sent the message...
                continue;//Skip to the next user since there is no purpose in sending the message back to the user who sent it.
            if (!SendString(i, Message)) //Send message to connection at index i, if message fails to be sent...
            {
                std::cout << "Failed to send message from client ID: " << ID << " to client ID: " << i << std::endl;
            }
        }
        //std::cout << "Processed chat message packet from user ID: " << ID << std::endl;
        if(Message == "go")
            std::cout << "MESSAGE:GO!"  << std::endl;
        else if(Message == "left")
            std::cout << "MESSAGE: GO LEFT!"  << std::endl;
        else if (Message == "right")
            std::cout << "MESSAGE:GO RIGHT!" << std::endl;
        else
            std::cout << "MESSAGE:DO NOTHING!" << std::endl;
        break;
    }
    default: //If packet type is not accounted for
    {
        std::cout << "Unrecognized packet: " << _packettype << std::endl; //Display that packet was not found
        break;
    }
    }
    return true;
}
void Server::ClientHandlerThread(int ID) //ID = the index in the SOCKET Connections array
{
    Packet PacketType;
    while (true)
    {
        if (!serverptr->GetPacketType(ID, PacketType)) //Get packet type
            break; //If there is an issue getting the packet type, exit this loop
        if (!serverptr->ProcessPacket(ID, PacketType)) //Process packet (packet type)
            break; //If there is an issue processing the packet, exit this loop
    }
    std::cout << "Lost connection to client ID: " << ID << std::endl;
    closesocket(serverptr->Connections[ID]);
    return;
}

有什么想法吗?

bind() 函数用于指定服务器系统的哪个地址用于接受来自远程客户端的连接,而不是指定允许哪个远程客户端连接到服务器。bind() 函数只能用于对服务器本身有效的地址,而不能用于远程设备或主机的地址。

为了限制允许哪个远程主机连接到您的服务器,您需要接受连接并在那时验证远程地址。如果地址不正确,则连接将关闭。

通常,除非服务器是多宿主的(到多个网络的多个物理连接),否则才要使用INADDR_ANY,并且只有在尝试限制与服务器连接到的网络之一的连接时才使用。

>每当应用程序尝试绑定到无效的 ip addrress 时,Winsock 都会通过其 API WSAGetLastError返回错误标志 10049 (WSAEADDRNOTAVAIL)。

绑定到特定 IP 地址意味着无论何时运行程序(服务器),该地址都应该有效(可用),但是 DHCP 会在您每次断开连接/连接适配器时为您提供动态 IP 地址,因此您上次绑定服务器的地址无效以更正它打开 cmd 并输入:

ipconfig

您将获得IP4/IP6地址的列表,然后您可以选择其中一个并将服务器绑定到但是此方法非常无聊,因此另一种方法是绑定到INADDR_ANY因此您让系统为您完成工作。

您只需从客户端输入服务器地址和端口并连接。