00001 /* 00002 Copyright (C) 2010 - 2017 Christoph Haenisch 00003 00004 Chair of Medical Engineering (mediTEC) 00005 RWTH Aachen University 00006 Pauwelsstr. 20 00007 52074 Aachen 00008 Germany 00009 00010 See license.txt for more information. 00011 00012 Version 0.1.2 (2017-12-07) 00013 */ 00014 00020 #include <cassert> 00021 #include <cstddef> 00022 #include <iostream> 00023 00024 #include "TRTK/ClientServer.hpp" 00025 00026 00027 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00028 // WINDOWS 00029 #include <winsock2.h> 00030 #include <ws2tcpip.h> 00031 #pragma comment(lib, "Ws2_32.lib") // link with Ws2_32.lib 00032 #else 00033 // Linux 00034 #include <arpa/inet.h> 00035 #include <netinet/in.h> 00036 #include <sys/types.h> 00037 #include <sys/socket.h> // Sometimes sys/socket.h doesn't include sys/types.h, so don't change the order! 00038 #include <unistd.h> 00039 #endif 00040 00041 00042 namespace TRTK 00043 { 00044 00045 00047 // Exceptions // 00049 00050 NetworkError::NetworkError(const std::string & what) : runtime_error(what) 00051 { 00052 } 00053 00054 00055 ConnectionClosed::ConnectionClosed(const std::string & what) : NetworkError(what) 00056 { 00057 } 00058 00059 00061 // Helper Functions // 00063 00064 enum {DATA_RECEIVED = 1}; 00065 00066 00073 void receive_all(int socket_fd, char * & data, size_t & size) 00074 { 00075 // Each block of data is preceded by a 16 bit word denoting the 00076 // size of the subsequent block of data. 00077 00078 char size_LSB = 0; // least significant byte is received first 00079 char size_MSB = 0; // most significant byte is received second 00080 00081 int error_code = recv(socket_fd, &size_LSB, 1, 0); 00082 00083 if (error_code == -1) 00084 { 00085 throw NetworkError("Error while receiving data."); 00086 } 00087 else if(error_code == 0) 00088 { 00089 throw ConnectionClosed("Error: Connection closed."); // EOF can be excluded 00090 } 00091 00092 error_code = recv(socket_fd, &size_MSB, 1, 0); 00093 00094 if (error_code == -1) 00095 { 00096 throw NetworkError("Error while receiving data."); 00097 } 00098 else if(error_code == 0) 00099 { 00100 throw ConnectionClosed("Error: Connection closed."); // EOF can be excluded 00101 } 00102 00103 size = ((unsigned short)(reinterpret_cast<unsigned char &>(size_MSB)) << 8) + 00104 (unsigned short)(reinterpret_cast<unsigned char &>(size_LSB)); 00105 00106 // A transmission can be accidentally disrupted (e.g. due to a kernel 00107 // interrupt). In that case recv() has to be called several times until 00108 // the remaining chunks of data are received. 00109 00110 size_t bytes_left = size; 00111 data = new char[size]; 00112 00113 while (bytes_left > 0) 00114 { 00115 int received_bytes = recv(socket_fd, &data[size - bytes_left], bytes_left, 0); // bytes_left must be of type 'size_t' according to 'The Single UNIX Specification, Version 2' 00116 00117 if (received_bytes == 0) 00118 { 00119 delete[] data; 00120 throw ConnectionClosed("Error: Connection closed."); // EOF can be excluded since we do not read more bytes than sent 00121 } 00122 00123 if (received_bytes == -1) 00124 { 00125 delete[] data; 00126 throw NetworkError("Error while receiving data."); 00127 } 00128 00129 bytes_left -= received_bytes; 00130 } 00131 00132 // Acknowledge the reception of data. 00133 // See send_all() for more details why this step is needed. 00134 00135 char transmission_confirmation = DATA_RECEIVED; 00136 00137 if (send(socket_fd, &transmission_confirmation, 1, 0) == -1) 00138 { 00139 delete[] data; 00140 throw NetworkError("Error while sending a transmission confirmation."); 00141 } 00142 } 00143 00144 00152 void send_all(int socket_fd, const char * data, size_t size) 00153 { 00154 assert(size >= 0 && size < 65536); // 65536 = 2^16 00155 if (size > 65536) throw NetworkError("Error: Maximum allowed data size is 65536 bytes."); 00156 00157 // Each block of data is preceded by a 16 bit word denoting the 00158 // size of the subsequent block of data. 00159 00160 char size_LSB = size & 0xFF; // least significant byte is send first 00161 char size_MSB = (size >> 8) & 0xFF; // most significant byte is send second 00162 00163 if (send(socket_fd, &size_LSB, 1, 0) == -1 || send(socket_fd, &size_MSB, 1, 0) == -1) 00164 { 00165 throw NetworkError("Error while sending data."); 00166 } 00167 00168 // A transmission can be accidentally disrupted (e.g. due to a kernel 00169 // interrupt). In that case send() has to be invoked several times 00170 // until the remaining chunks of data are fully transmitted. 00171 00172 size_t bytes_left = size; 00173 00174 while (bytes_left > 0) 00175 { 00176 int sent_bytes = send(socket_fd, &data[size - bytes_left], bytes_left, 0); // bytes_left must be of type 'size_T' according to 'The Single UNIX Specification, Version 2' 00177 if (sent_bytes == -1) throw NetworkError("Error while sending data."); 00178 bytes_left -= sent_bytes; 00179 } 00180 00181 // Receive the transmission confirmation. 00182 00183 // From [http://bert-hubert.blogspot.de/]: 00184 // 00185 // > It turns out that in this case, section 4.2.2.13 of RFC 1122 tells us that a 00186 // > close() with any pending readable data could lead to an immediate reset being sent. 00187 // > 00188 // > "A host MAY implement a 'half-duplex' TCP close sequence, so that an application 00189 // > that has called CLOSE cannot continue to read data from the connection. If such a 00190 // > host issues a CLOSE call while received data is still pending in TCP, or if new 00191 // > data is received after CLOSE is called, its TCP SHOULD send a RST to show that 00192 // > data was lost." 00193 // 00194 // Solution (should always work regardless of the TCP stack implementation): 00195 // 00196 // To avoid a potential data loss, a sender can send length information and the receiver 00197 // actively acknowledges that all data was received. 00198 00199 char transmission_confirmation = 0; 00200 00201 int error_code = recv(socket_fd, &transmission_confirmation, 1, 0); 00202 00203 if (error_code == -1) 00204 { 00205 throw NetworkError("Error while getting a transmission confirmation."); 00206 } 00207 else if (error_code == 0) 00208 { 00209 throw ConnectionClosed("Error: Connection closed."); // EOF can be excluded 00210 } 00211 00212 if (transmission_confirmation != DATA_RECEIVED) 00213 { 00214 throw NetworkError("Transmission failed."); 00215 } 00216 } 00217 00218 00220 // Client // 00222 00223 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00224 static int num_winsock_instances = 0; 00225 #endif 00226 00227 00230 Client::Client() : connected(false) 00231 { 00232 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00233 // Initialize Winsock 00234 00235 WSADATA wsaData = {0}; 00236 int retval = WSAStartup(MAKEWORD(2, 2), &wsaData); 00237 if (retval != 0) 00238 { 00239 throw(NetworkError("Error: WSAStartup failed.")); 00240 } 00241 00242 ++num_winsock_instances; 00243 #endif 00244 } 00245 00246 00249 Client::~Client() 00250 { 00251 if (connected) 00252 { 00253 disconnect(); 00254 } 00255 00256 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00257 if (num_winsock_instances > 0) 00258 { 00259 WSACleanup(); 00260 --num_winsock_instances; 00261 } 00262 #endif 00263 } 00264 00265 00272 void Client::connect(std::string host, short port) 00273 { 00274 // Set up a socket. 00275 00276 socket_fd = static_cast<int>(socket(AF_INET, SOCK_STREAM, 0)); // returns type 'int' according to 'The Single UNIX Specification, Version 2' 00277 00278 if (socket_fd == -1) 00279 { 00280 throw(NetworkError("Error while setting up the stream socket.")); 00281 } 00282 00283 // Assign a name to the socket (binding). 00284 00285 sockaddr_in address = {0}; 00286 address.sin_family = AF_INET; 00287 address.sin_addr.s_addr = inet_addr(host.c_str()); 00288 address.sin_port = htons(port); 00289 00290 socklen_t sockaddr_in_size = sizeof(sockaddr_in); 00291 00292 if (::connect(socket_fd, reinterpret_cast<sockaddr *>(&address), sockaddr_in_size) == -1) 00293 { 00294 throw NetworkError("Error while establishing a connection."); 00295 } 00296 00297 connected = true; 00298 } 00299 00300 00303 void Client::disconnect() 00304 { 00305 if (connected) 00306 { 00307 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00308 closesocket(socket_fd); 00309 #else 00310 close(socket_fd); 00311 #endif 00312 00313 connected = false; 00314 } 00315 } 00316 00317 00326 void Client::receiveData(char * & data, size_t & size) 00327 { 00328 receive_all(socket_fd, data, size); 00329 } 00330 00331 00346 std::pair<char *, size_t> Client::request(const char * data, size_t size) 00347 { 00348 char * received_data = NULL; 00349 size_t received_data_size = 0; 00350 00351 sendData(data, size); 00352 receiveData(received_data, received_data_size); 00353 00354 return std::pair<char *, size_t>(received_data, received_data_size); 00355 } 00356 00357 00363 void Client::sendData(const char * data, size_t size) 00364 { 00365 send_all(socket_fd, data, size); 00366 } 00367 00368 00370 // Server // 00372 00375 Server::Server() : close_connection(false), stop_server(false) 00376 { 00377 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00378 // Initialize Winsock 00379 00380 WSADATA wsaData = {0}; 00381 int retval = WSAStartup(MAKEWORD(2, 2), &wsaData); 00382 if (retval != 0) 00383 { 00384 throw(NetworkError("Error: WSAStartup failed.")); 00385 } 00386 00387 ++num_winsock_instances; 00388 #endif 00389 } 00390 00391 00394 Server::~Server() 00395 { 00396 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00397 if (num_winsock_instances > 0) 00398 { 00399 WSACleanup(); 00400 --num_winsock_instances; 00401 } 00402 #endif 00403 } 00404 00405 00414 void Server::closeConnection() 00415 { 00416 close_connection = true; 00417 } 00418 00419 00440 void Server::receiveData(char * & data, size_t & size) 00441 { 00442 receive_all(client_fd, data, size); 00443 } 00444 00445 00451 void Server::sendData(const char * data, size_t size) 00452 { 00453 send_all(client_fd, data, size); 00454 } 00455 00456 00465 void Server::startServer(short port) 00466 { 00467 // Set up a socket. 00468 00469 int server_fd = static_cast<int>(socket(AF_INET, SOCK_STREAM, 0)); // returns type 'int' according to 'The Single UNIX Specification, Version 2' 00470 00471 if (server_fd == -1) 00472 { 00473 throw(NetworkError("Error while setting up the stream socket.")); 00474 } 00475 00476 // Assign a name to the socket (binding). 00477 00478 sockaddr_in address = {0}; 00479 address.sin_family = AF_INET; 00480 address.sin_addr.s_addr = htonl(INADDR_ANY); 00481 address.sin_port = htons(port); 00482 00483 socklen_t sockaddr_in_size = sizeof(sockaddr_in); 00484 00485 if (bind(server_fd, reinterpret_cast<sockaddr*>(&address), sockaddr_in_size) == -1) 00486 { 00487 throw NetworkError("Error while binding the stream socket."); 00488 } 00489 00490 while (!stop_server) 00491 { 00492 // Listen to a client. 00493 00494 if (listen(server_fd, 5) == -1) 00495 { 00496 throw NetworkError("Error while listening for connections."); 00497 } 00498 00499 // Accecpt a connection. 00500 00501 sockaddr_in client_address; 00502 client_fd = static_cast<int>(accept(server_fd, reinterpret_cast<sockaddr*>(&client_address), &sockaddr_in_size)); // returns type 'int' according to 'The Single UNIX Specification, Version 2' 00503 00504 if (client_fd == -1) 00505 { 00506 throw NetworkError("Error while accepting the connection."); 00507 } 00508 00509 close_connection = false; 00510 00511 try 00512 { 00513 while (!close_connection) 00514 { 00515 // Read the data/request. 00516 00517 char * data = NULL; 00518 size_t data_size = 0; 00519 00520 try 00521 { 00522 receiveData(data, data_size); 00523 } 00524 catch (ConnectionClosed) 00525 { 00526 delete[] data; 00527 break; 00528 } 00529 00530 // Hand the data on to the derived class. 00531 00532 std::pair<char *, size_t> reply = handleRequest(data, data_size); 00533 00534 // Send the server's answer to the client. 00535 00536 try 00537 { 00538 sendData(reply.first, reply.second); 00539 } 00540 catch (ConnectionClosed) 00541 { 00542 delete[] reply.first; 00543 delete[] data; 00544 break; 00545 } 00546 catch(...) 00547 { 00548 delete[] reply.first; 00549 delete[] data; 00550 throw; 00551 } 00552 00553 // Clean up. 00554 00555 delete[] reply.first; 00556 delete[] data; 00557 } 00558 } 00559 catch (NetworkError) 00560 { 00561 // There seems to be a connection problem so close the 00562 // current connection and listen to new clients. 00563 00564 std::cerr << "Server error: Client connection died..." << std::endl; 00565 } 00566 00567 // Close the connection. 00568 00569 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00570 closesocket(client_fd); 00571 #else 00572 close(client_fd); 00573 #endif 00574 } 00575 00576 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) 00577 closesocket(server_fd); 00578 #else 00579 close(server_fd); 00580 #endif 00581 00582 stop_server = false; 00583 } 00584 00585 00588 void Server::stopServer() 00589 { 00590 stop_server = true; 00591 } 00592 00593 00594 } // namespace TRTK
Documentation generated by Doxygen