Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - radario

Pages: [1]
1
Network / Undesired behaviour in Linux networking code
« on: June 13, 2012, 11:41:26 pm »
Hi.

I have a tcp server listening on a thread, wating for connections from clients. When the program is closed, I close the server's socket, but the server keeps accept-ing.

Here's some test code:

#include <stdlib.h>

#include "ServerThreadTest.h"
#include "VBClient.h"
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#include <vector>
#include <iostream>

namespace ThreadTest {

    class Server {
    public:

        Server(int port) : _port(port), _running(false), _socket(new sf::TcpListener()) {
            std::cout << "Server blocking: " << _socket->isBlocking() << std::endl;
            sf::TcpSocket::Status status = _socket->listen(port);

            if (status != sf::TcpSocket::Done) {
                _running = false;
            } else {
                _running = true;
            }
        };

        ~Server() {
            this->close();

            if (_socket) {
                delete(_socket);
            }
            _socket = NULL;
           
        };

        void run() {
            while (_running) {
                sf::TcpSocket socket;

                std::cout << "Server: waiting for a connection ..." << std::endl;

                sf::TcpSocket::Status status = _socket->accept(socket);

                if (status == sf::TcpSocket::Done) {
                    std::cout << "Server: client incoming" << std::endl;
                    //                    sockets.push_back(socket);

                    socket.disconnect();

                } else {
                    switch (status) {
                        case sf::TcpSocket::Disconnected:
                            std::cout << "DISCONNECTED" << std::endl;
                            break;
                        case sf::TcpSocket::Error:
                            std::cout << "ERROR" << std::endl;
                            break;
                        case sf::TcpSocket::NotReady:
                            std::cout << "NOT READY" << std::endl;
                            break;
                    }

                    _running = false;
                }
            }

            std::cout << "Server: I leave" << std::endl;

        };

        void running(bool b) {
            _running = b;
        };

        bool running() {
            return _running;
        };

        void close() {

            // Useless
            _running = false;

            if (_socket) {
                _socket->close();
            }
        };

    private:
        int _port;
        bool _running;
        sf::TcpListener *_socket;

    };
};

int ServerThreadTest() {

    const int porta = 8080;

    ThreadTest::Server server(porta);

    sf::Thread thread(&ThreadTest::Server::run, &server);

    thread.launch();

    sf::IpAddress address("localhost");
    for (int i = 0; i < 10; i++) {

        std::cout << "Connection try #" << i << std::endl;

        sf::TcpSocket socket;

        if (socket.connect(address, porta, sf::seconds(1)) != sf::TcpSocket::Done) {
            std::cout << "Connection error" << std::endl;
        }
       
        sf::sleep(sf::seconds(1.0f));

    }

    server.close();

    std::cout << "I'd leave, if you don't mind..." << std::endl;

    return EXIT_SUCCESS;
}

This behaviour is related to what is described in this StackOverflow post:

http://stackoverflow.com/questions/9365282/c-linux-accept-blocking-after-socket-closed

I'm willing to send a signal to that thread, but it seems it's not possible to get the thread handle with the current API.

terminate() the thread is not an option, since it leaves the file descriptor opened.

Having a non-blocking socket with small sleeps between accept()s is quite ugly, too.

Another workaround is to put _running to false, then starting another connection to the server, so that the socket will close in its thread.

Is there a way to manage this situation cleanly?

Thanks in advance:)

radario

2
Network / Packet reception - interoperability with Java (?)
« on: May 09, 2012, 11:47:48 pm »
Hi, I'm new here, hello to everybody:)

I'm trying to send strings from Java to an SFML application, via TCP, and I want to use the packet abstraction, which I found nice.

Java-wise, the code is this:

String message = "something";
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
int length = message.getBytes().length + 4;
dos.writeInt(length);
dos.writeBytes(message);            
dos.flush();

In SFML, the following code doesn't work:

sf::Packet packet;
socket.receive(packet);
std::cout << "Packet size: " << packet.getDataSize() << std::endl;
std::string stringa;
packet >> stringa;        
std::cout << stringa << std::endl;

The problem is that packet.getDataSize() returns 0, and subsequently nothing is received.
In order to debug this, I tried to call directly socket.receive, and I discovered that it receives 1 byte at a time, even if I specify 4 of them (to receive the first int with the size of the packet);

So, to properly receive the packet I wrote this:

char *dataSize = new char[4];

std::size_t received = 0;
std::size_t receivedSoFar = 0;

do {
   socket.receive((void *) (dataSize + receivedSoFar), 1, received);
   receivedSoFar += received;            
} while (receivedSoFar < 4);

then I convert the 4 char to a number, I allocate a proper buffer, and then I happily receive, with the same mechanism, the rest of the string.
I also noticed that socket.receive, when called on a connection coming from a C++ SFML application, does indeed receives 4 bytes at a time. Maybe it's related to the fact that when receiving a packet sent from Java, only the first byte is read, then it's treated as a whole int and as such its value is zero.

I'm running SFML RC1 as packaged in ArchLinux.

Bye:)

Pages: [1]
anything