Clean thread exit

better nonblocking socket mode support
This commit is contained in:
IMback 2017-11-05 22:07:26 +01:00
parent e07866b906
commit 7603d1c59d
3 changed files with 78 additions and 20 deletions

View File

@ -129,6 +129,14 @@ void Socket::setKeepalive()
setsockopt(sockDesc, SOL_SOCKET, TCP_KEEPINTVL, &optval, sizeof(optval));
}
void Socket::setBlocking(bool flag)
{
int flags = fcntl(sockDesc, F_GETFL, 0);
if( !flag ) flags = flags | O_NONBLOCK;
else flags = flags & ~O_NONBLOCK;
fcntl(sockDesc, F_SETFL, flags);
}
void Socket::cleanUp() {
}
@ -240,15 +248,22 @@ TCPServerSocket::TCPServerSocket(const string &localAddress, unsigned short loca
TCPSocket* TCPServerSocket::accept()
{
int newConnSD;
if ((newConnSD = ::accept(sockDesc, NULL, 0)) < 0 )
int newConnSD = -1;
if ((newConnSD = ::accept(sockDesc, NULL, 0)) < 0 && errno != EAGAIN && errno != EWOULDBLOCK )
{
throw SocketException("Accept failed (accept())", true);
}
if(keepalive) setKeepalive();
return new TCPSocket(newConnSD);
TCPSocket* newSocket = nullptr;
if(newConnSD > 0)
{
newSocket = new TCPSocket(newConnSD);
if(keepalive) newSocket->setKeepalive();
}
return newSocket;
}
void TCPServerSocket::setListen(int queueLen) {
if (listen(sockDesc, queueLen) < 0) {
throw SocketException("Set listening socket failed (listen())", true);

View File

@ -102,6 +102,7 @@ public:
const std::string &protocol = "tcp");
void setKeepalive();
void setBlocking(bool flag);
private:
// Prevent the user from trying to use value semantics on this object
@ -231,6 +232,7 @@ public:
*/
TCPSocket *accept() ;
private:
void setListen(int queueLen) ;
bool keepalive;

View File

@ -7,6 +7,7 @@
#include <cstdlib>
#include <vector>
#include <thread>
#include <signal.h>
#include "serial_io.h"
#include "Socket.h"
@ -20,12 +21,40 @@ void intHandler(int dummy)
static void printUsage()
{
std::cout<<"usage mulitplexer [option]-\n\
Available options:\n\
-h, --help print this help\n\
-p, --serialport serial port device to use\n\
-P, --port tcp port to use\n\
-b, --baud set baud rate with termios id\n";
std::cout<<"usage mulitplexer [option]\n\
Available options:\n\
-h, --help print this help\n\
-p, --serialport serial port device to use\n\
-P, --port tcp port to use\n\
-b, --baud set baud rate with termios id\n\
-r, --rates list Available baud rates\n";
}
static void printRates()
{
std::cout<<"Rates:\n\
B50 0000001\n\
B75 0000002\n\
B110 0000003\n\
B134 0000004\n\
B150 0000005\n\
B200 0000006\n\
B300 0000007\n\
B600 0000010\n\
B1200 0000011\n\
B1800 0000012\n\
B2400 0000013\n\
B4800 0000014\n\
B9600 0000015\n\
B19200 0000016\n\
B38400 0000017\n\
B57600 0010001\n\
B115200 0010002\n\
B500000 0010005\n\
B1000000 0010010\n\
B1152000 0010011\n\
B1500000 0010012\n\
B2000000 0010013";
}
class Config
@ -60,17 +89,27 @@ static int parseCmdArgs(int argc, char** argv, Config *config)
if(argc > i+1) config->baud = atoi(argv[i+1]);
else return -1;
}
else if (std::string(argv[i]) == "-r" || std::string(argv[i]) == "--rates")
{
printRates();
return -1;
}
}
return 0;
}
void acceptThreadFunction( TCPServerSocket* servSock, std::vector<TCPSocket*>* clientSockets, volatile bool* stop )
void acceptThreadFunction( TCPServerSocket* servSock, std::vector<TCPSocket*>* clientSockets )
{
while(!(*stop))
{ // Run forever
clientSockets->push_back(servSock->accept()); // Wait for a client to connect
clientSockets->back()->send("UVOS serial port multiplexer v0.1\n", sizeof("uvos serial port multiplexer v0.1\n")-1);
std::cout<<"got client\n";
while(!stop)
{
TCPSocket* newSock = servSock->accept();
if(newSock != nullptr)
{
clientSockets->push_back(newSock); // Wait for a client to connect
clientSockets->back()->send("UVOS serial port multiplexer v0.1\n", sizeof("uvos serial port multiplexer v0.1\n")-1);
std::cout<<"got client\n";
}
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
@ -88,12 +127,15 @@ int main(int argc, char* argv[])
std::cout<<"opening TCP socet on port "<<config.port<<'\n';
TCPServerSocket servSock(config.port, 5, true); // Server Socket object
servSock.setBlocking(false);
volatile bool threadStopper = false;
std::thread acceptThread(acceptThreadFunction, &servSock, &clientSockets, &threadStopper);
std::thread acceptThread(acceptThreadFunction, &servSock, &clientSockets);
char buffer[256];
signal(SIGINT, intHandler);
//signal(SIGTERM, intHandler);
std::cout<<"starting loop\n";
while(!stop)
@ -123,7 +165,7 @@ int main(int argc, char* argv[])
}
else if(reclen == 0)
{
std::cout<<"disconnect client "<<i<<'\n';
std::cout<<"client "<<i<<" disconnected"<<'\n';
clientSockets[i]->cleanUp();
clientSockets.erase(clientSockets.begin()+i);
i--;
@ -142,7 +184,6 @@ int main(int argc, char* argv[])
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
threadStopper = true;
acceptThread.join();
for(unsigned int i = 0; i < clientSockets.size(); i++) clientSockets[i]->cleanUp();
servSock.cleanUp();