返回

C++ Winsock关闭插座

发布时间:2022-09-07 20:38:50 396
# golang

所以我一直在 UE4 中创建一个 winsock 服务器/客户端。我可以让客户端连接到服务器,但是一旦客户端发送了第一条消息,它似乎就关闭了套接字,从而阻止了任何进一步的消息发送到服务器。似乎服务器在发送数据时也在做同样的事情。

客户

// Convert IP & port to standard lib
    const std::string IP = std::string(TCHAR_TO_UTF8((*GameInstance->GetIPAddress())));
    const std::string PORT = std::string(TCHAR_TO_UTF8(*GameInstance->GetPort()));
    // Set the version of WSA we are using
    auto Version = MAKEWORD(2, 2);
    WSAData WSData;
    struct addrinfo* Result = nullptr, * ptr = nullptr, hints;

    int iResult;                // Store Initializing results
    std::string message;        // Define a message to send to the server

    UE_LOG(LogTemp, Log, TEXT("Starting Client"));

    // Initialize WinSock
   
    iResult = WSAStartup(Version, &WSData);         // Start winsock
    if(iResult != 0)
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to initialize winsock"));
        return ECreateConnectionFlag::WINSOCK_FAILED;
    }
    
    UE_LOG(LogTemp, Log, TEXT("Initialized WinSock"));

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

    UE_LOG(LogTemp, Log, TEXT("Connecting"));

    // Get the address details
    iResult = getaddrinfo(IP.c_str(), PORT.c_str(), &hints, &Result);
    if(iResult != 0)
    {
        UE_LOG(LogTemp, Error, TEXT("Error getting address info from the server"));
        WSACleanup();
        return 0;
    }

    // Connect the player
    for(ptr = Result; ptr != nullptr; ptr->ai_next)
    {
        GameInstance->SetPlayerSocket(socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol));
        if(GameInstance->GetLoggedInPlayer().PlayerSocket == INVALID_SOCKET)
        {
            UE_LOG(LogTemp, Error, TEXT("Failed to create socket"));
            WSACleanup();
            return 0;
        }

        iResult = connect(GameInstance->GetLoggedInPlayer().PlayerSocket, ptr->ai_addr, ptr->ai_addrlen);
        if(iResult == SOCKET_ERROR)
        {
            closesocket(GameInstance->GetLoggedInPlayer().PlayerSocket);
            GameInstance->SetPlayerSocket(INVALID_SOCKET);
            continue;
        }
        break;
    }

    freeaddrinfo(Result);               // Release Address information as it's no longer required

    // Ensure the socket is valid
    if(GameInstance->GetLoggedInPlayer().PlayerSocket == INVALID_SOCKET)
    {
        UE_LOG(LogTemp, Error, TEXT("Unable to connect to server..."));
        WSACleanup();
        return 0;
    }

    

    // WE ARE CONNECTED

    /* CONNECT AND SEND USERNAME */
    FString SignInMessage = FString("Username-" + GameInstance->GetLoggedInPlayer().Username);
    std::string ConnectionMessage = std::string(TCHAR_TO_UTF8(*SignInMessage));
    iResult = send(GameInstance->GetLoggedInPlayer().PlayerSocket, ConnectionMessage.c_str(), (int)strlen(ConnectionMessage.c_str()), 0);
    if(iResult <= 0)
    {
        int error = WSAGetLastError();
        UE_LOG(LogTemp, Error, TEXT("Failed to send message: %d"), error);
        return 0;
    }
    
    
    while(bRunThread)
    {
        UE_LOG(LogTemp, Log, TEXT("Receiving Data"));
        /* DISCONNECT FROM SERVER */
        const std::string msg = "Hello World";
        iResult = send(GameInstance->GetLoggedInPlayer().PlayerSocket, msg.c_str(), (int)strlen(msg.c_str()), 0);
        if(iResult <= 0)
        {
            int error = WSAGetLastError();
            UE_LOG(LogTemp, Error, TEXT("Failed to send message: %d"), error);
            return 0;
        }
        FPlatformProcess::Sleep(1.0f);
    }

    /* DISCONNECT FROM SERVER */
    const std::string DisconnectMsg = "Disconnect";
    iResult = send(GameInstance->GetLoggedInPlayer().PlayerSocket, DisconnectMsg.c_str(), (int)strlen(DisconnectMsg.c_str()), 0);
    if(iResult <= 0)
    {
        int error = WSAGetLastError();
        UE_LOG(LogTemp, Error, TEXT("Failed to send message: %d"), error);
        return 0;
    }

    UE_LOG(LogTemp, Warning, TEXT("Client Disconnected"));
    closesocket(GameInstance->GetLoggedInPlayer().PlayerSocket);
    WSACleanup();
    return 0;
}

服务器

    WSAData wsa;                
    struct addrinfo hints;                          // Server Hint details
    struct addrinfo* server = NULL;                 // Address info of the server
    SOCKET serverSocket = INVALID_SOCKET;           // Server Listening Socket

    PlayerArray* Players = new PlayerArray();           // Reference to all the players in the server
    LobbyArray* Lobbies = new LobbyArray();             // Reference to all the lobbies in the server


    // Initialize the winsock library
    std::cout << "Initializing WinSock..." << std::endl;
    int WSA_Init = WSAStartup(MAKEWORD(2, 2), &wsa);
    if (WSA_Init != 0)
    {
        std::cerr << "Error Initializing Winsock";
        WSACleanup();
        return;
    }
    else
    {
        std::cout << "Winsock Initialized" << std::endl;
    }

    // Setup Hints
    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Setup the server
    std::cout << "Setting up Server" << std::endl;
    getaddrinfo(IP_ADDRESS, PORT, &hints, &server);

    // Create the listening socket
    std::cout << "Creating Listening socket" << std::endl;
    serverSocket = socket(server->ai_family, server->ai_socktype, server->ai_protocol);
    if (serverSocket == INVALID_SOCKET)
    {
        std::cerr << "Failed creating listening socket" << std::endl;
        WSACleanup();
        return;
    }
    else
    {
        std::cout << "Created listen socket" << std::endl;
    }

    // Set the socket to be TCP
    setsockopt(serverSocket, IPPROTO_TCP, TCP_NODELAY, &OPTION_VALUE, sizeof(int));

    // Bind the socket
    std::cout << "Binding Socket..." << std::endl;
    bind(serverSocket, server->ai_addr, (int)server->ai_addrlen);

    // Start the server
    std::cout << "Server has started & is listening..." << std::endl;
    listen(serverSocket, SOMAXCONN);

    while (true)
    {

        std::cout << "Players Connected: " << Players->Count() << std::endl;
        SOCKET Incoming = INVALID_SOCKET;               // Define a socket for anything incoming
        Incoming = accept(serverSocket, NULL, NULL);        // Accept the incoming message from the socket

        // If the socket is not valid than continue through the loop
        if (Incoming == INVALID_SOCKET)
        {
            std::cout << "Invalid Socket" << std::endl;
            continue;
        }
        else
        {
            std::cout << "Valid Socket" << std::endl;
        }
            

        char tempmsg[DFT_BUFLEN] = "";                  // Define a temp msg to store the message from the client
        int received = recv(Incoming, tempmsg, DFT_BUFLEN, 0);          // Receive a message from the client
        
        std::string convertedMessage = tempmsg;

        // Check that the received message is from a valid socket
        if (received != SOCKET_ERROR)
        {
            
            std::string message = tempmsg;              // Assing the temp message to a string to split
            if (convertedMessage == "Disconnect")
            {
                Players->RemovePlayer(Incoming);
                std::cout << "Player Disconnected..." << std::endl;
                continue;
            }
            else
            {
                std::cout << tempmsg << std::endl;                      // === DEBUG ===
                // Split the string
                char* next_split;
                char* split_string = strtok_s(tempmsg, "-", &next_split);
                std::string FirstMsg = split_string;
                if (FirstMsg == "Username")
                {
                    std::cout << next_split << " Has joined the server" << std::endl;           // Server message
                    // Get the player that we want to set the username to

                    // Create the player and add it to the server list
                    Player* NewPlayer = new Player();
                    Players->AddPlayer(NewPlayer);

                    NewPlayer->SetUsername(next_split);         // Set the usernames
                    continue;
                    

                }
                else if (split_string == "Lobby")
                {
                    if (next_split == "Create")
                    {
                        Lobby* NewLobby = Lobbies->CreateLobby();               // Create a new lobby
                        Player* SocketPlayer = Players->GetPlayerBySocket(Incoming);        // Get the player creating it by socket

                        // ensure that the player is valid, if so add the player to the lobby
                        // Otherwise send an error message to the console.
                        if (SocketPlayer != nullptr)            
                        {
                            NewLobby->AddPlayerToLobby(SocketPlayer);
                        }
                        else
                        {
                            std::cerr << "Failed Locate player to add to lobby" << std::endl;
                        }
                    }
                    else if (next_split == "Destroy")
                    {
                        // TODO: Destroy Specific lobby
                    }

                    continue;
                }
                else
                {
                    std::cout << "Error Reading Message" << std::endl;
                }
            }
        }
        else
        {
            std::cerr << "Socket Error when recieving message" << std::endl;
        }

        

    }

    // Clean up the server
    delete Players;
    delete Lobbies;
    closesocket(serverSocket);
    WSACleanup();



    return;

断开后的控制台输出

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(1)
按点赞数排序
用户头像