winsock错误10049试图绑定

时间:2017-01-08 21:09:16

标签: c++ sockets tcp

我遇到服务器连接问题。当我尝试将服务器绑定到我的外部设备IP时,我得到了一个winsock错误:10049无法分配请求的地址。使用localhost服务器正常工作。 此IP地址:192.168.0.202 ping成功。 我参与了win8.1。我关闭了防火墙和Windows后卫,但没有帮助。

服务器实施的代码取自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;
}

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

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

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

通常,您希望使用INADDR_ANY,除非您的服务器是多宿主(多个网络的多个物理连接),并且只有在您尝试限制与其中一个网络的连接时才会使用function superInsecureHash(string) { return string.length; } console.log(superInsecureHash("Hello world!")); // 12 您的服务器所附加的。

答案 1 :(得分:1)

只要应用程序尝试绑定到无效的IP地址,Winsock就会通过其API WSAGetLastError返回错误标志10049(WSAEADDRNOTAVAIL)。

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

ipconfig

你将获得ip4 / ip6地址的列表然后你可以选择其中一个并绑定你的服务器但是这个方法真的很无聊所以另一种方法是绑定到INADDR_ANY所以你让系统做适合你的工作。

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