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-closedI'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