SFML community forums

Help => Network => Topic started by: Derpington on March 29, 2013, 09:56:59 pm

Title: [SOLVED] Client can't reconnect to server
Post by: Derpington on March 29, 2013, 09:56:59 pm
This may be a network programming problem rather than something to do with SFML.
The problem is going like this :

Launch the server.
Launch the client.
if(selector.isReady(listener)) is running.
Shut the client down.
Timeout is detected.
Launch the client back, without closing the server.
if(selector.isReady(listener)) isn't running.

This is the server code :

#include <iostream>
#include <list>

#include <SFML/Network.hpp>

std::vector<sf::TcpSocket*> clients;
sf::SocketSelector selector;

int main(int argc, char **argv) {
    std::cout << "Update server initiated!" << std::endl;

    sf::TcpListener listener;
    listener.listen(90);
    listener.setBlocking(false);

    selector.add(listener);

    while(true) {
        if(selector.wait()) {
            if(selector.isReady(listener)) {
                sf::TcpSocket* client = new sf::TcpSocket;
                if(listener.accept(*client) == sf::Socket::Done) {
                    clients.push_back(client);
                    selector.add(*client);
                    std::cout << "Connection from client " << client->getRemoteAddress() << "!" << std::endl;
                }
            } else {
                std::vector<sf::TcpSocket*>::iterator it;
                for(it = clients.begin(); it != clients.end(); it++) {
                    sf::TcpSocket* client = *it;
                    if(selector.isReady(*client)) {
                        sf::Packet packet;
                        if(client->receive(packet) == sf::Socket::Done) {
                            std::string data;
                            packet >> data;
                            std::cout << "Received data : " << data << std::endl;
                            if(data[0] == '0') {
                                std::string message = data.substr(1);
                                if(message == "abstergo") {
                                    sf::Packet response;
                                    std::string responseString = "1";
                                    response << responseString;
                                    std::cout << "Client " << client->getRemoteAddress() << " logged in." << std::endl;
                                    client->send(response);
                                }
                            }
                        } else {
                            std::cout << "Timeout detected from " << (*it)->getRemoteAddress() << std::endl;
                            (*it)->disconnect();
                            selector.remove(**it);
                            delete (*it);
                            it = clients.erase(it);
                            it--;
                        }
                    }
                }
            }
        }
    }

    std::cin.get();
    return 0;
}
 
Title: Re: Client can't reconnect to server
Post by: Laurent on March 29, 2013, 10:05:46 pm
Any message in the console?

You can't reuse the same port so quickly, there's a short delay. That may explain your problem.

By the way, checking the the return value of functions that return a status (TcpListener::listen) is strongly recommended ;)
Title: Re: Client can't reconnect to server
Post by: Derpington on March 29, 2013, 10:12:14 pm
The console output when I proceed to the steps from my first post is :
Quote
Update server initiated!
Connection from client 192.168.1.1!
Timeout detected from 192.168.1.1

As you can see there's nothing stating the connection from the second client.

Regarding your second point, which port are you referring to? The listener's port?
Title: Re: Client can't reconnect to server
Post by: Derpington on March 30, 2013, 12:46:15 am
I changed my server code to this and it works fine now, but I don't know exactly why :

#include <iostream>
#include <list>

#include <SFML/Network.hpp>

int main(int argc, char **argv) {
    std::cout << "Update server initiated!" << std::endl;

    std::vector<sf::TcpSocket*> clients;

    sf::TcpListener listener;
    if(listener.listen(90) != sf::Socket::Status::Done)
        std::cout << "Couldn't listen to port 90!" << std::endl;
    listener.setBlocking(false);

    sf::SocketSelector selector;
    selector.add(listener);

    while(true) {
        if(selector.wait()) {
            if(selector.isReady(listener)) {
                sf::TcpSocket* client = new sf::TcpSocket;
                if(listener.accept(*client) == sf::Socket::Status::Done) {
                    std::cout << "Connection from client " << client->getRemoteAddress() << "!" << std::endl;
                    clients.push_back(client);
                    selector.add(*client);
                }
            } else {
                for(int i = 0; i < clients.size(); ++i) {
                    if(selector.isReady(*clients[i])) {
                        sf::Packet packet;
                        if(clients[i]->receive(packet) == sf::Socket::Status::Done) {
                            std::string data;
                            packet >> data;
                           if(data[0] == '1') {
                                std::string message = data.substr(1);
                                if(message == "abstergo") {
                                    sf::Packet response;
                                    std::string responseString = "1";
                                    response << responseString;
                                    std::cout << "Client " << clients[i]->getRemoteAddress() << " logged in." << std::endl;
                                    clients[i]->send(response);
                                }
                            } if(data[0] == '2') {
                                std::cout << "Received hearbeat from " << clients[i]->getRemoteAddress() << "." << std::endl;
                            }
                        } else {
                            std::cout << "Timeout detected from " << clients[i]->getRemoteAddress() << std::endl;
                            selector.remove(*clients[i]);
                            delete clients[i];
                        }
                    }
                }
            }
        }
    }

    std::cin.get();
    return 0;
}
 

Also, for future reference :
#include <iostream>
#include <vector>
#include <string>
#include <SFML/Network.hpp>

void doServer() {
    std::cout << "Started server. " << std::endl;
    std::vector<sf::TcpSocket*> clients;

    sf::TcpListener listener;
    listener.listen(90);

    sf::SocketSelector selector;
    selector.add(listener);

    while(true) {
        if(selector.wait()) {
            if(selector.isReady(listener)) {
                sf::TcpSocket* client = new sf::TcpSocket();
                if(listener.accept(*client) == sf::Socket::Status::Done) {
                    std::cout << "Accepted new connection from " << client->getRemoteAddress() << ". " << std::endl;
                    clients.push_back(client);
                    selector.add(*client);
                }
            } else {
                for(int i = 0; i < clients.size(); ++i) {
                    if(selector.isReady(*clients[i])) {
                        sf::Packet packet;
                        if(clients[i]->receive(packet) == sf::Socket::Status::Done) {
                            std::string message;
                            packet >> message;

                            std::cout << "Received message from " << clients[i]->getRemoteAddress() << " : " << message << std::endl;
                        } else {
                            std::cout << "Client " << clients[i]->getRemoteAddress() << " disconnected." << std::endl;
                            selector.remove(*clients[i]);
                            delete clients[i];
                        }
                    }
                }
            }
        }
    }
}

void doClient() {
    std::cout << "Started client. " << std::endl;
    sf::TcpSocket socket;
    if(! socket.connect("127.0.0.1", 90) == sf::Socket::Status::Done) {
        std::cout << "Couldn't connect to server." << std::endl;
        return;
    } else
        std::cout << "Connected to server." << std::endl;
    std::cin.ignore(1000);
    std::cin.get();
}

int main(int argc, char **argv) {
    std::cout << "c/s ? ";
    std::string input;
    std::cin >> input;
    if(input == "c")
        doClient();
    if(input == "s")
        doServer();

    std::cin.get();
    return 0;
}
 
Title: Re: [SOLVED] Client can't reconnect to server
Post by: Laurent on March 30, 2013, 12:07:31 pm
I don't know (don't really have time to investigate, sorry).

Why do you put a non-blocking socket in a selector? It just doesn't make sense.