tdaq-develop-2025-02-12
TCPServer.cc
1 #include "otsdaq/NetworkUtilities/TCPServer.h"
2 #include <errno.h> // errno
3 #include <string.h> // errno
4 #include "otsdaq/NetworkUtilities/TCPTransceiverSocket.h"
5 
6 #include <iostream>
7 using namespace ots;
8 
9 //==============================================================================
10 TCPServer::TCPServer(unsigned int serverPort, unsigned int maxNumberOfClients)
11  : TCPServerBase(serverPort, maxNumberOfClients), fInDestructor(false)
12 
13 {
14  fReceiveTimeout.tv_sec = 0;
15  fReceiveTimeout.tv_usec = 0;
16  fSendTimeout.tv_sec = 0;
17  fSendTimeout.tv_usec = 0;
18  // fAcceptFuture = std::async(std::launch::async, &TCPServer::acceptConnections,
19  // this);
20 }
21 
22 //==============================================================================
23 TCPServer::~TCPServer(void) { fInDestructor = true; }
24 
25 //==============================================================================
28 void TCPServer::connectClient(TCPTransceiverSocket* socket)
29 {
30  while(true)
31  {
32  // std::cout << __PRETTY_FUNCTION__ << "Waiting for message for socket #: " << socket->getSocketId() << std::endl;
33  std::string message;
34  try
35  {
36  // The server should only communicate with packets
37  //...otherwise the messages could be incomplete
38  message = socket->receivePacket();
39  }
40  catch(const std::exception& e)
41  {
42  if(!fInDestructor)
43  {
44  std::cout << __PRETTY_FUNCTION__ << "Error client socket #"
45  << socket->getSocketId() << ": " << e.what()
46  << std::endl; // Client connection must have closed
47  TCPServerBase::closeClientSocket(socket->getSocketId());
48  interpretMessage("Error: " + std::string(e.what()));
49  }
50  return;
51  }
52 
53  // std::cout << __PRETTY_FUNCTION__
54  //<< "Received message:-" << message << "-"
55  //<< "Message Length=" << message.length() << " From socket #: " << socket->getSocketId() << std::endl;
56  std::string messageToClient = interpretMessage(message);
57 
58  // Send back something only if there is actually a message to be sent!
59  if(messageToClient != "")
60  {
61  // std::cout << __PRETTY_FUNCTION__ << "Sending back message:-" << messageToClient << "-(nbytes=" << messageToClient.length() << ") to socket #: "
62  // << socket->getSocketId() << std::endl;
63  socket->sendPacket(messageToClient);
64  }
65  // else
66  // std::cout << __PRETTY_FUNCTION__ << "Not sending anything back to socket #: " << socket->getSocketId() << std::endl;
67 
68  // std::cout << __PRETTY_FUNCTION__ << "After message sent now checking for more... socket #: " << socket->getSocketId() << std::endl;
69  }
70  // If the socket is removed then this line will crash.
71  // It is crucial then to have the return when the exception is caught and the socket is closed!
72  std::cout << __PRETTY_FUNCTION__
73  << "Thread done for socket #: " << socket->getSocketId() << std::endl;
74  // std::cout << __PRETTY_FUNCTION__ << "Thread done for socket!" << std::endl;
75 }
76 
77 //==============================================================================
78 void TCPServer::acceptConnections()
79 {
80  // std::pair<std::unordered_map<int, TCPTransceiverSocket>::iterator, bool> element;
81  while(true)
82  {
83  try
84  {
85  TCPTransceiverSocket* clientSocket = acceptClient<TCPTransceiverSocket>();
86  clientSocket->setReceiveTimeout(fReceiveTimeout.tv_sec,
87  fReceiveTimeout.tv_usec);
88  clientSocket->setSendTimeout(fSendTimeout.tv_sec, fSendTimeout.tv_usec);
89  if(fConnectedClientsFuture.find(clientSocket->getSocketId()) !=
90  fConnectedClientsFuture.end())
91  fConnectedClientsFuture.erase(
92  fConnectedClientsFuture.find(clientSocket->getSocketId()));
93  fConnectedClientsFuture.emplace(
94  clientSocket->getSocketId(),
95  std::async(
96  std::launch::async, &TCPServer::connectClient, this, clientSocket));
97  // fConnectedClientsFuture.emplace(clientSocket->getSocketId(), std::thread(&TCPServer::connectClient, this, clientSocket));
98  }
99  catch(int e)
100  {
101  if(e == E_SHUTDOWN)
102  break;
103  }
104  }
105  // fAcceptPromise.set_value(true);
106 }
107 
108 //==============================================================================
109 void TCPServer::setReceiveTimeout(unsigned int timeoutSeconds,
110  unsigned int timeoutMicroseconds)
111 {
112  fReceiveTimeout.tv_sec = timeoutSeconds;
113  fReceiveTimeout.tv_usec = timeoutMicroseconds;
114 }
115 
116 //==============================================================================
117 void TCPServer::setSendTimeout(unsigned int timeoutSeconds,
118  unsigned int timeoutMicroseconds)
119 {
120  fSendTimeout.tv_sec = timeoutSeconds;
121  fSendTimeout.tv_usec = timeoutMicroseconds;
122 }
A class that can read/write to a socket.