38 #include <system_error>
44 TCPServer::TCPServer(
const int port,
const size_t max_num_tries,
const std::chrono::milliseconds reconnection_time)
45 : port_(port), maxfd_(0), max_clients_allowed_(0)
49 ::WSAStartup(MAKEWORD(1, 1), &data);
53 bind(max_num_tries, reconnection_time);
69 throw std::system_error(std::error_code(errno, std::generic_category()),
"Failed to create socket endpoint");
87 socket_t shutdown_socket = ::socket(AF_INET, SOCK_STREAM, 0);
90 throw std::system_error(std::error_code(errno, std::generic_category()),
"Unable to create shutdown socket.");
94 unsigned long mode = 1;
95 ::ioctlsocket(shutdown_socket, FIONBIO, &mode);
97 int flags = ::fcntl(shutdown_socket, F_GETFL, 0);
100 ::fcntl(shutdown_socket, F_SETFL, flags | O_NONBLOCK);
104 struct sockaddr_in address;
105 memset(&address, 0,
sizeof(address));
106 address.sin_family = AF_INET;
107 address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
108 address.sin_port = htons(
port_);
110 ::connect(shutdown_socket,
reinterpret_cast<const sockaddr*
>(&address),
sizeof(address));
120 void TCPServer::bind(
const size_t max_num_tries,
const std::chrono::milliseconds reconnection_time)
122 struct sockaddr_in server_addr;
123 server_addr.sin_family = AF_INET;
126 server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
127 server_addr.sin_port = htons(
port_);
129 size_t connection_counter = 0;
132 err =
::bind(
listen_fd_, (
struct sockaddr*)&server_addr,
sizeof(server_addr));
135 std::ostringstream ss;
136 ss <<
"Failed to bind socket for port " <<
port_ <<
" to address. Reason: " << strerror(errno);
138 if (connection_counter++ < max_num_tries || max_num_tries == 0)
140 std::this_thread::sleep_for(reconnection_time);
141 ss <<
"Retrying in " << std::chrono::duration_cast<std::chrono::duration<float>>(reconnection_time).count()
147 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
150 }
while (err == -1 && (connection_counter <= max_num_tries || max_num_tries == 0));
163 std::ostringstream ss;
164 ss <<
"Failed to start listen on port " <<
port_;
165 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
172 struct sockaddr_storage client_addr;
173 socklen_t addrlen =
sizeof(client_addr);
177 std::ostringstream ss;
178 ss <<
"Failed to accept connection request on port " <<
port_;
179 throw std::system_error(std::error_code(errno, std::generic_category()), ss.str());
197 URCL_LOG_WARN(
"Connection attempt on port %d while maximum number of clients (%d) is already connected. Closing "
209 int sel = select(
static_cast<int>(
maxfd_ + 1), &
tempfds_, NULL, NULL, NULL);
212 URCL_LOG_ERROR(
"select() failed. Shutting down socket event handler.");
276 if (errno == ECONNRESET)
278 URCL_LOG_DEBUG(
"client from FD %d sent a connection reset package.", fd);
313 size_t remaining = buf_len;
316 while (written < buf_len)
318 ssize_t sent = ::send(fd,
reinterpret_cast<const char*
>(buf + written),
static_cast<socklen_t
>(remaining), 0);