Проблемы с моим приложением winsock

0

У меня проблемы с приложением Winsock.

Поскольку в настоящее время он стоит, когда мой клиент сначала подключается к серверу, приветственное сообщение отправляется в порядке, но это когда он завинчивается. После этого начального сообщения его, как программа, переходит в режим turbo.

У каждого клиента есть вектор, который хранит сообщения, которые необходимо отправить, для отладки. У меня есть вывод, сколько сообщений осталось отправить, и вот что говорит последний:

    Successfully sent message. 1 messages left.
    Successfully sent message. 1574803 messages left
    ................... (Counts down)
    Successfully sent message. 1574647 messages left
    Client connection closed or broken

РЕДАКТИРОВАТЬ: Управляемый для размещения некоторого выходного кода в нужном месте, по какой-то причине, когда он начинает отправлять сообщения об обновлениям клиентам, он начинает отправлять одно и то же сообщение снова и снова.

Вот какой код, я только отправляю сообщение cpp, 'Network :: Update' запускается потоком в 'Game'

- Сервер -

main.cpp

    while(true)
    {
        m_Game -> Update();
        Sleep(500);
    }

Network.cpp

    #include "Network.h"

    Network::Network()
    {
    }

    Network::~Network()
    {
        closesocket(m_Socket);
    }

    Network::Network(char* ServerIP, int ServerPort)
    {
        Initialise(ServerIP, ServerPort);
    }

    void Network::Initialise(char* ServerIP, int ServerPort)
    {
        //
        // Initialise the winsock library to 2.2
        //
        WSADATA w;
        int error = WSAStartup(0x0202, &w);
        if ((error != 0)    || (w.wVersion != 0x0202))
        {
            MessageBox(NULL, L"Winsock error. Shutting down.", L"Notification", MB_OK);
            exit(1);
        }

        //
        // Create the TCP socket
        //
        m_Socket = socket(AF_INET, SOCK_STREAM, 0);
        if (m_Socket == SOCKET_ERROR)
        {
            MessageBox(NULL, L"Failed to create socket.", L"Notification", MB_OK);
            exit(1);
        }

        //
        // Fill out the address structure
        //
        m_Address.sin_family = AF_INET;
        m_Address.sin_addr.s_addr = inet_addr(ServerIP);
        m_Address.sin_port = htons(ServerPort);

        //
        // Bind the server socket to that address.
        //
        if (bind(m_Socket, (const sockaddr *) &m_Address, sizeof(m_Address)) != 0)
        {
            MessageBox(NULL, L"Failed to bind the socket to the address.", L"Notification", MB_OK);
            exit(1);
        }

        //
        // Make the socket listen for connections.
        //
        if (listen(m_Socket, 1) != 0)
        {
            MessageBox(NULL, L"Failed to listen on the socket.", L"Notification", MB_OK);
            exit(1);
        }

        m_ID = 1;
    }

    void Network::Update()
    {
        //
        // Structures for the sockets
        //
        fd_set readable, writeable;
        FD_ZERO(&readable);
        FD_ZERO(&writeable);

        //
        // Let the socket accept connections
        //
        FD_SET(m_Socket, &readable);

        //
        // Cycle through clients allowing them to read and write
        //
        for (std::list<Client *>::iterator it = m_Clients.begin(); it != m_Clients.end(); ++it)
        {
            Client *client = *it;

            if (client->wantRead())
            {
                FD_SET(client->sock(), &readable);
            }

            if (client->wantWrite())
            {
                FD_SET(client->sock(), &writeable);
            }
        }

        //
        // Structure defining the connection time out
        //
        timeval timeout;
        timeout.tv_sec = 2;
        timeout.tv_usec = 500000;

        //
        // Check if a socket is readable
        //
        int count = select(0, &readable, &writeable, NULL, &timeout);
        if (count == SOCKET_ERROR)
        {
            ExitProgram(L"Unable to check if the socket can be read.\nREASON: Select failed");
        }

        //
        // Check if a theres an incoming connection
        //
        if (FD_ISSET(m_Socket, &readable))
        {
            //
            // Accept the incoming connection
            //
            sockaddr_in clientAddr;
            int addrSize = sizeof(clientAddr);
            SOCKET clientSocket = accept(m_Socket, (sockaddr *) &clientAddr, &addrSize);
            if (clientSocket > 0)
            {
                // Create a new Client object, and add it to the collection.
                Client *client = new Client(clientSocket);
                m_Clients.push_back(client);

                // Send the new client a welcome message.
                NetworkMessage message;
                message.m_Type = MT_Welcome;
                client->sendMessage(message);

                m_ID++;
            }
        }

        //
        // Loop through clients
        //
        for (std::list<Client *>::iterator it = m_Clients.begin(); it != m_Clients.end(); )  // note no ++it here
        {
            Client *client = *it;
            bool dead = false;

            //
            // Read data
            //
            if (FD_ISSET(client->sock(), &readable))
            {
                dead = client->doRead();
            }

            //
            // Write data
            //
            if (FD_ISSET(client->sock(), &writeable))
            {
                dead = client->doWrite();
            }

            //
            // Check if the client is dead (Was unable to write/read packets)
            //
            if (dead)
            {
                delete client;
                it = m_Clients.erase(it);
            }
            else
            {
                ++it;
            }
        }
    }

    void Network::sendMessage(NetworkMessage message)
    {
        //Loop through clients and send them the message
        for (std::list<Client *>::iterator it = m_Clients.begin(); it != m_Clients.end(); )  // note no ++it here
        {
            Client *client = *it;
            client->sendMessage(message);
        }
    }

client.cpp

    #include "Client.h"

    Client::Client(SOCKET sock)
    {
        m_Socket = sock;
        send_count_ = 0;
    }

    // Destructor.
    Client::~Client()
    {
        closesocket(m_Socket);
    }

    // Process an incoming message.
    void Client::processMessage(NetworkMessage message)
    {
        // PROCESSING NEEDS TO GO HERE
    }

    // Return the client socket.
    SOCKET Client::sock()
    {
        return m_Socket;
    }

    // Return whether this connection is in a state where we want to try
    // reading from the socket.
    bool Client::wantRead()
    {
        // At present, we always do.
        return true;
    }

    // Return whether this connection is in a state where we want to try-
    // writing to the socket.
    bool Client::wantWrite()
    {
        // Only if we've got data to send.
        //return send_count_ > 0;

        return Messages.size() > 0;
    }

    // Call this when the socket is ready to read.
    // Returns true if the socket should be closed.
    bool Client::doRead()
    {
        return false;
    }

    // Call this when the socket is ready to write.
    // Returns true if the socket should be closed.
    bool Client::doWrite()
    {
        /*int count = send(m_Socket, send_buf_, send_count_, 0);
        if (count <= 0)
        {
            printf("Client connection closed or broken\n");
            return true;
        }

        send_count_ -= count;

        // Remove the sent data from the start of the buffer.
        memmove(send_buf_, &send_buf_[count], send_count_);

        return false;*/

        int count = send(m_Socket, (char*)&Messages[0], sizeof(NetworkMessage), 0);
        if( count <= 0 )
        {
            printf("Client connection closed or broken\n");
            return true;
        }
        Messages.pop_back();
        printf(" Successfully sent message. %d messages left.\n", Messages.size() );

        return false;
    }

    void Client::sendMessage(NetworkMessage message)
    {
        /*if (send_count_ + sizeof(NetworkMessage) > sizeof(send_buf_))
        {
            ExitProgram(L"Unable to send message.\nREASON: send_buf_ full");
        }
        else
        {
            memcpy(&send_buf_[send_count_], message, sizeof(NetworkMessage));
            send_count_ += sizeof(NetworkMessage);
            printf(" Size of send_count_ : %d \n", send_count_);
        }*/

        Messages.push_back(message);
    }

Game.cpp

    void Game::Update()
    {
        tempPlayer -> ChangePosition(1, 1); //Increase X and Y pos by 1

        Dispatch();
        printf("Update\n");
    }

    void Game::Dispatch()
    {
        NetworkMessage temp;
        temp.m_Type = MT_Update;
        temp.m_ID = tempPlayer->getID();
        temp.m_positionX = tempPlayer->getX();
        temp.m_positionY = tempPlayer->getY();

        m_Network->sendMessage(temp);
    }
  • 0
    Вы пытались использовать отладчик, чтобы выяснить, что идет не так?
  • 0
    Использовал точки останова и выходные данные printf, но не могу понять это
Теги:
console
winsock

1 ответ

2
Лучший ответ

Есть несколько проблем с вашим кодом.

Основная проблема заключается в том, что Network::sendMessage() запускает бесконечный цикл. Ваш it итератор никогда не увеличивается (есть комментарий говоря, как много - комментарий делают неправильные вещи!), Так что цикл посылает то же NetworkMessage к тому же Client снова и снова, никогда не останавливаясь. Сделайте это вместо этого:

void Network::sendMessage(NetworkMessage message)
{
    //Loop through clients and send them the message
    for (std::list<Client *>::iterator it = m_Clients.begin(); it != m_Clients.end(); ++it)
    {
        ...
    }
}

Client::doWrite() использует pop_back() когда он должен использовать pop_front(). Если в векторе есть несколько ожидающих сообщений, вы потеряете сообщения. Вместо того, чтобы использовать оператор [] для передачи NetworkMessage непосредственно для send(), вы должны pop_front() первое ожидающее сообщение, а затем send() его:

bool Client::doWrite()
{
    NetworkMessage message = Messages.pop_front();

    int count = send(m_Socket, (char*)&message, sizeof(NetworkMessage), 0);
    if( count <= 0 )
    {
        printf("Client connection closed or broken\n");
        return true;
    }

    printf(" Successfully sent message. %d messages left.\n", Messages.size() );
    return false;
}

Ваша dead проверка в Network::Update() имеет небольшое логическое отверстие, которое может помешать вам удалить мертвых клиентов правильно, если doRead() возвращает true, а затем doWrite() возвращает false. Сделайте это вместо этого:

bool dead = false;

//
// Read data
//
if (FD_ISSET(client->sock(), &readable))
{
    if (client->doRead())
        dead = true;
}

//
// Write data
//
if (FD_ISSET(client->sock(), &writeable))
{
    if (client->doWrite())
        dead = true; 
}
  • 0
    Спасибо! Полностью пропустил тот факт, что я пропустил оператор приращения итератора lol!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню