3#pragma warning(disable:4996)
10#include <netinet/in.h>
22#define INVALID_SOCKET -1
23#define SOCKET_ERROR -1
24#define closesocket(s) ::close(s)
28 typedef int socklen_t;
37mutex& ref_show_mutex()
43int socket::nr_of_sockets= 0;
44bool socket::show_debug_output =
false;
49 show_debug_output = enable;
58 if (WSAStartup(MAKEWORD(2,0), &info)) {
59 if (show_debug_output) {
60 ref_show_mutex().
lock();
61 std::cerr <<
"could not start up windows socket dll" << std::endl;
68 if (show_debug_output) {
69 ref_show_mutex().
lock();
70 std::cout <<
"successfully start up windows socket dll" << std::endl;
80 if (--nr_of_sockets == 0) {
84 if (show_debug_output) {
85 ref_show_mutex().
lock();
86 std::cout <<
"cleaned up windows socket dll" << std::endl;
107 getsockopt(
user_data, SOL_SOCKET, SO_ERROR, buffer, &len);
112 if (show_debug_output) {
113 ref_show_mutex().
lock();
114 std::cerr <<
"socket error: ";
117 std::cerr << location <<
" - " <<
last_error.c_str();
118 ref_show_mutex().
unlock();
143 return select(0, &set, 0, 0, &t) == 1;
150 set_last_error(
"get_nr_of_arrived_bytes",
"socket not connected");
155 if (ioctlsocket(
user_data, FIONREAD, &arg) != 0) {
162 std::cerr <<
"get_nr_of_arrived_bytes not implemented!!!" << std::endl;
173 if (nr_of_bytes == 0) {
175 int received_nr_of_bytes = recv (
user_data, buf, 1024, 0);
176 if (received_nr_of_bytes <= 0) {
177 set_last_error(
"receive_data", received_nr_of_bytes == SOCKET_ERROR ?
"" :
"connection closed");
180 ret += std::string(buf,received_nr_of_bytes);
184 while (nr_of_bytes > 0) {
185 int received_nr_of_bytes = recv(
user_data, buf, min(1024, (
int)nr_of_bytes), 0);
186 if (received_nr_of_bytes <= 0) {
187 set_last_error(
"receive_data", received_nr_of_bytes == SOCKET_ERROR ?
"" :
"connection closed");
190 ret += std::string(buf,received_nr_of_bytes);
191 nr_of_bytes -= received_nr_of_bytes;
205 set_last_error(
"receive_line", result == SOCKET_ERROR ?
"" :
"connection closed");
211 if (show_debug_output) {
212 ref_show_mutex().
lock();
213 std::cout <<
"received line: " << ret.c_str();
215 ref_show_mutex().
unlock();
229 int nr_bytes = (int)s.length();
230 const char* buf = s.c_str();
232 int nr_bytes_sent = send(
user_data, buf, nr_bytes, 0);
233 if (nr_bytes_sent <= 0)
234 return set_last_error(
"send_data/line", nr_bytes_sent == SOCKET_ERROR ?
"" :
"connection closed");
235 nr_bytes -= nr_bytes_sent;
236 buf += nr_bytes_sent;
237 }
while (nr_bytes > 0);
252 if (show_debug_output) {
253 ref_show_mutex().
lock();
254 std::cout <<
"socket(" <<
user_data <<
") closed successfully" << std::endl;
255 ref_show_mutex().
unlock();
274 return set_last_error(
"connect",
"could not initialize os specific socket shared library");
282 if ((he = gethostbyname(host.c_str())) == 0)
285 addr.sin_family = AF_INET;
286 addr.sin_port = htons(port);
287 addr.sin_addr = *((in_addr *)he->h_addr);
288 memset(&(addr.sin_zero), 0, 8);
291 if (show_debug_output) {
292 ref_show_mutex().
lock();
293 std::cout <<
"successfully connected socket_client(" <<
user_data <<
")" << std::endl;
294 ref_show_mutex().
unlock();
311 return set_last_error(
"bind_and_listen",
"could not initialize os specific socket shared library");
313 memset(&sa, 0,
sizeof(sa));
314 sa.sin_family = PF_INET;
315 sa.sin_port = htons(port);
319 return set_last_error(
"bind_and_listen",
"could not create socket");
322 if (bind(
user_data, (sockaddr *)&sa,
sizeof(sockaddr_in)) == SOCKET_ERROR) {
328 if (listen((SOCKET)
user_data, max_nr_connections) != 0)
331 if (show_debug_output) {
332 ref_show_mutex().
lock();
333 std::cout <<
"successfully bound socket_server(" <<
user_data <<
") to port " << port << std::endl;
334 ref_show_mutex().
unlock();
343 set_last_error(
"wait_for_connection",
"attempt to wait for connection of socket server that does not listen to port");
350 int flags = fcntl(
user_data, F_GETFD) & (~O_NONBLOCK);
353 SOCKET new_sock = ::accept(
user_data, 0, 0);
354 if (new_sock == INVALID_SOCKET) {
359 if (show_debug_output) {
360 ref_show_mutex().
lock();
361 std::cout <<
"received new connection on socket_server(" <<
user_data <<
"): " << new_sock << std::endl;
362 ref_show_mutex().
unlock();
372 set_last_error(
"check_for_connection",
"attempt to check for connection of socket server that does not listen to port");
381 SOCKET new_sock = ::accept(
user_data, 0, 0);
382 if (new_sock == INVALID_SOCKET) {
384 if (WSAGetLastError() == WSAEWOULDBLOCK) {
386 if (errno == EAGAIN || errno == EWOULDBLOCK) {
395 if (show_debug_output) {
396 ref_show_mutex().
lock();
397 std::cout <<
"received new connection on socket_server(" <<
user_data <<
"): " << new_sock << std::endl;
398 ref_show_mutex().
unlock();
reference counted pointer, which can work together with types that are derived from ref_counted,...
socket_client()
hide from direct use
bool connect(const std::string &host, int port)
connect to given port of given host, if the socket is already connected, close this connection first
socket server allows to be connected to
bool bind_and_listen(int port, int max_nr_pending_connections)
bind and listen to given port with a queue for pending connections of the given size
socket_server()
hide from direct use
socket_ptr wait_for_connection()
if no connection is pending, block thread and wait for next incoming connection
socket_ptr check_for_connection()
check if a new connection is in the connection queue and return this or an empty connection pointer
friend CGV_API socket_server_ptr create_socket_server()
this is the only way to create a socket_server as a reference counted pointer
static void enable_debug_output(bool enable=true)
enables or disables (default) debug output for all socket commands
bool send_line(const std::string &content)
extends line by newline and send as data
virtual ~socket()
virtual destructor
std::string receive_data(unsigned int nr_of_bytes=0)
receive all pending data or if nr_of_bytes is larger than 0, exactly nr_of_bytes
socket()
hides constructor from user
bool set_last_error(const char *location, const std::string &text="") const
convenience function to set last error and print debug info. The method always returns false.
bool send_data(const std::string &)
send the data in the string
std::string receive_line()
receive data up to the next newline excluding the newline char
bool is_data_pending() const
return whether data has arrived
size_t user_data
store platform dependent reference to socket
std::string get_last_error() const
returns the last error
std::string last_error
store the last error
int get_nr_of_arrived_bytes() const
return the number of data bytes that have been arrived at the socket or -1 if socket is not connected
bool close()
close the socket
void unlock()
unlock the mutex
void lock()
lock the mutex (if the mutex is already locked, the caller is blocked until the mutex becomes availab...