From 761b7b93543ad2e8dfd307ee3679b3a2a7082ddc Mon Sep 17 00:00:00 2001 From: curt Date: Fri, 10 May 2002 13:53:22 +0000 Subject: [PATCH] Bernie Bright: Here's a first cut at SGSocket reimplemented using plib.net. I've maintained the same TCP server behaviour, that is only one client connection at a time. I don't think it is possible within the current framework to handle simultaneous clients. I've also added two simple test programs, tcp_client and tcp_server. --- simgear/io/Makefile.am | 18 +- simgear/io/iochannel.cxx | 2 - simgear/io/sg_socket.cxx | 518 +++++++++++++------------------------- simgear/io/sg_socket.hxx | 43 +--- simgear/io/tcp_client.cxx | 77 ++++++ simgear/io/tcp_server.cxx | 69 +++++ 6 files changed, 356 insertions(+), 371 deletions(-) create mode 100644 simgear/io/tcp_client.cxx create mode 100644 simgear/io/tcp_server.cxx diff --git a/simgear/io/Makefile.am b/simgear/io/Makefile.am index b00e2445..ef61ff85 100644 --- a/simgear/io/Makefile.am +++ b/simgear/io/Makefile.am @@ -32,7 +32,21 @@ else NETWORK_LIB = endif -noinst_PROGRAMS = decode_binobj socktest lowtest +noinst_PROGRAMS = decode_binobj socktest lowtest tcp_server tcp_client + +tcp_server_SOURCES = tcp_server.cxx + +tcp_server_LDADD = \ + $(top_builddir)/simgear/io/libsgio.a \ + $(top_builddir)/simgear/debug/libsgdebug.a \ + -lplibnet + +tcp_client_SOURCES = tcp_client.cxx + +tcp_client_LDADD = \ + $(top_builddir)/simgear/io/libsgio.a \ + $(top_builddir)/simgear/debug/libsgdebug.a \ + -lplibnet socktest_SOURCES = socktest.cxx @@ -42,7 +56,7 @@ socktest_LDADD = \ $(top_builddir)/simgear/debug/libsgdebug.a \ $(top_builddir)/simgear/misc/libsgmisc.a \ $(top_builddir)/simgear/xml/libsgxml.a \ - -lz + -lplibnet -lz lowtest_SOURCES = lowtest.cxx diff --git a/simgear/io/iochannel.cxx b/simgear/io/iochannel.cxx index ea8372cf..4d034895 100644 --- a/simgear/io/iochannel.cxx +++ b/simgear/io/iochannel.cxx @@ -22,8 +22,6 @@ #include "iochannel.hxx" -// #include "garmin.hxx" -// #include "nmea.hxx" // constructor diff --git a/simgear/io/sg_socket.cxx b/simgear/io/sg_socket.cxx index 43735428..b348ddf1 100644 --- a/simgear/io/sg_socket.cxx +++ b/simgear/io/sg_socket.cxx @@ -1,6 +1,7 @@ // sg_socket.cxx -- Socket I/O routines // // Written by Curtis Olson, started November 1999. +// Modified by Bernie Bright , May 2002. // // Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org // @@ -23,16 +24,6 @@ #include -#if !defined(_MSC_VER) && !defined(__MINGW32__) -# include // select() -# include // socket(), bind(), select(), accept() -# include // socket(), bind(), listen(), accept() -# include // struct sockaddr_in -# include // gethostbyname() -# include // select(), fsync()/fdatasync(), fcntl() -# include // fcntl() -#endif - #if defined( sgi ) #include #endif @@ -41,25 +32,30 @@ #include "sg_socket.hxx" +bool SGSocket::init = false; -SGSocket::SGSocket( const string& host, const string& port, +SGSocket::SGSocket( const string& host, const string& port_, const string& style ) : hostname(host), - port_str(port), - save_len(0) + port_str(port_), + save_len(0), + client(0), + is_tcp(false), + is_server(false), + first_read(false) { -#if defined(_MSC_VER) || defined(__MINGW32__) - if (!wsock_init && !wsastartup()) { - SG_LOG( SG_IO, SG_ALERT, "Winsock not available"); + if (!init) + { + netInit(); + init = true; } -#endif - if ( style == "udp" ) { - sock_style = SOCK_DGRAM; - } else if ( style == "tcp" ) { - sock_style = SOCK_STREAM; - } else { - sock_style = SOCK_DGRAM; + if ( style == "tcp" ) + { + is_tcp = true; + } + else if ( style != "udp" ) + { SG_LOG( SG_IO, SG_ALERT, "Error: SGSocket() unknown style = " << style ); } @@ -68,126 +64,65 @@ SGSocket::SGSocket( const string& host, const string& port, } -SGSocket::~SGSocket() { +SGSocket::~SGSocket() +{ + this->close(); } -SGSocket::SocketType SGSocket::make_server_socket () { - struct sockaddr_in name; - -#if defined( __CYGWIN__ ) || defined( __CYGWIN32__ ) || defined( sgi ) || defined( _MSC_VER ) || defined(__MINGW32__) || defined( __APPLE__ ) - int length; -#else - socklen_t length; -#endif - - // Create the socket. - sock = socket (PF_INET, sock_style, 0); - if (sock == INVALID_SOCKET) { +bool +SGSocket::make_server_socket() +{ + if (!sock.open( is_tcp )) + { SG_LOG( SG_IO, SG_ALERT, "Error: socket() failed in make_server_socket()" ); - return INVALID_SOCKET; - } - - // Give the socket a name. - name.sin_family = AF_INET; - name.sin_addr.s_addr = INADDR_ANY; - name.sin_port = htons(port); // set port to zero to let system pick - name.sin_addr.s_addr = htonl (INADDR_ANY); - if (bind (sock, (struct sockaddr *) &name, sizeof (name)) != 0) { - SG_LOG( SG_IO, SG_ALERT, - "Error: bind() failed in make_server_socket()" ); - return INVALID_SOCKET; + return false; } - // Find the assigned port number - length = sizeof(struct sockaddr_in); - if ( getsockname(sock, (struct sockaddr *) &name, &length) ) { + if (sock.bind( "", port ) < 0) + { SG_LOG( SG_IO, SG_ALERT, - "Error: getsockname() failed in make_server_socket()" ); - return INVALID_SOCKET; + "Error: bind() failed in make_server_socket()" ); + sock.close(); + return false; } - port = ntohs(name.sin_port); - return sock; + return true; } -SGSocket::SocketType SGSocket::make_client_socket () { - struct sockaddr_in name; - struct hostent *hp; - - SG_LOG( SG_IO, SG_INFO, "Make client socket()" ); - - // Create the socket. - sock = socket (PF_INET, sock_style, 0); - if (sock == INVALID_SOCKET) { +bool +SGSocket::make_client_socket() +{ + if (!sock.open( is_tcp )) + { SG_LOG( SG_IO, SG_ALERT, - "Error: socket() failed in make_server_socket()" ); - return INVALID_SOCKET; - } - - // specify address family - name.sin_family = AF_INET; - - // get the hosts official name/info - hp = gethostbyname( hostname.c_str() ); - if (hp == NULL) { - SG_LOG( SG_IO, SG_ALERT, "Error: hostname lookup failed" ); - return INVALID_SOCKET; + "Error: socket() failed in make_client_socket()" ); + return false; } - // Connect this socket to the host and the port specified on the - // command line -#if defined( __CYGWIN__ ) || defined( __CYGWIN32__ ) - bcopy(hp->h_addr, (char *)(&(name.sin_addr.s_addr)), hp->h_length); -#else - bcopy(hp->h_addr, &(name.sin_addr.s_addr), hp->h_length); -#endif - name.sin_port = htons(port); - - if ( connect(sock, (struct sockaddr *) &name, - sizeof(struct sockaddr_in)) != 0 ) + if (sock.connect( hostname.c_str(), port ) < 0) { - closesocket(sock); SG_LOG( SG_IO, SG_ALERT, "Error: connect() failed in make_client_socket()" ); - return INVALID_SOCKET; + sock.close(); + return false; } - return sock; -} - - -// Wrapper functions -int SGSocket::readsocket( int fd, void *buf, size_t count ) { -#if defined(_MSC_VER) || defined(__MINGW32__) - return ::recv( fd, (char *)buf, count, 0 ); -#else - return ::read( fd, buf, count ); -#endif -} - -int SGSocket::writesocket( int fd, const void *buf, size_t count ) { -#if defined(_MSC_VER) || defined(__MINGW32__) - return ::send( fd, (const char*)buf, count, 0 ); -#else - return ::write( fd, buf, count ); -#endif -} - -#if !defined(_MSC_VER) && !defined(__MINGW32__) -int SGSocket::closesocket( int fd ) { - return ::close( fd ); + return true; } -#endif - // If specified as a server (in direction for now) open the master // listening socket. If specified as a client (out direction), open a // connection to a server. -bool SGSocket::open( const SGProtocolDir d ) { - set_dir( d ); +bool +SGSocket::open( SGProtocolDir direction ) +{ + set_dir( direction ); + + is_server = is_tcp && + (direction == SG_IO_IN || direction == SG_IO_BI); if ( port_str == "" || port_str == "any" ) { port = 0; @@ -195,69 +130,71 @@ bool SGSocket::open( const SGProtocolDir d ) { port = atoi( port_str.c_str() ); } - // client_connections.clear(); - - if ( get_dir() == SG_IO_IN ) { + if (direction == SG_IO_IN) + { // this means server for now // Setup socket to listen on. Set "port" before making this // call. A port of "0" indicates that we want to let the os // pick any available port. - sock = make_server_socket(); - if ( sock == INVALID_SOCKET ) { - SG_LOG( SG_IO, SG_ALERT, "socket creation failed" ); + if (!make_server_socket()) + { + SG_LOG( SG_IO, SG_ALERT, "SG_IO_IN socket creation failed" ); return false; } - SG_LOG( SG_IO, SG_INFO, "socket is connected to port = " << port ); - - if ( sock_style == SOCK_DGRAM ) { + if ( !is_tcp ) + { // Non-blocking UDP nonblock(); - } else { + } + else + { // Blocking TCP // Specify the maximum length of the connection queue - listen( sock, SG_MAX_SOCKET_QUEUE ); + sock.listen( SG_MAX_SOCKET_QUEUE ); } - } else if ( get_dir() == SG_IO_OUT ) { + } + else if (direction == SG_IO_OUT) + { // this means client for now - sock = make_client_socket(); - // TODO: check for error. + if (!make_client_socket()) + { + SG_LOG( SG_IO, SG_ALERT, "SG_IO_OUT socket creation failed" ); + return false; + } - if ( sock_style == SOCK_DGRAM ) { + if ( !is_tcp ) + { // Non-blocking UDP nonblock(); } - } else if ( get_dir() == SG_IO_BI && sock_style == SOCK_STREAM ) { + } + else if (direction == SG_IO_BI && is_tcp) + { // this means server for TCP sockets // Setup socket to listen on. Set "port" before making this // call. A port of "0" indicates that we want to let the os // pick any available port. - sock = make_server_socket(); - // TODO: check for error. - - SG_LOG( SG_IO, SG_INFO, "socket is connected to port = " << port ); - + if (!make_server_socket()) + { + SG_LOG( SG_IO, SG_ALERT, "SG_IO_BI socket creation failed" ); + return false; + } // Blocking TCP // Specify the maximum length of the connection queue - listen( sock, SG_MAX_SOCKET_QUEUE ); - } else { + sock.listen( SG_MAX_SOCKET_QUEUE ); + } + else + { SG_LOG( SG_IO, SG_ALERT, "Error: bidirection mode not available for UDP sockets." ); return false; } - if ( sock < 0 ) { - SG_LOG( SG_IO, SG_ALERT, "Error opening socket: " << hostname - << ":" << port ); - return false; - } - - // extra SOCK_STREAM stuff - msgsock = INVALID_SOCKET; first_read = false; return true; @@ -266,40 +203,25 @@ bool SGSocket::open( const SGProtocolDir d ) { // read data from socket (server) // read a block of data of specified size -int SGSocket::read( char *buf, int length ) { - if ( sock == INVALID_SOCKET ) { +int +SGSocket::read( char *buf, int length ) +{ + if (sock.getHandle() == -1 && + (client == 0 || client->getHandle() == -1)) + { return 0; } - int result = 0; - // check for potential input - fd_set ready; - FD_ZERO(&ready); - FD_SET(sock, &ready); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - // test for any input available on sock (returning immediately, even if // nothing) - select(32, &ready, 0, 0, &tv); - - if ( FD_ISSET(sock, &ready) ) { - // cout << "data ready" << endl; - - if ( sock_style == SOCK_STREAM ) { - if ( msgsock == INVALID_SOCKET ) { - msgsock = accept(sock, 0, 0); - closesocket(sock); - sock = msgsock; - } else { - result = readsocket( sock, buf, length ); - } - } else { - result = readsocket( sock, buf, length ); - } + int result = poll(); + + if (result > 0) + { + result = sock.recv( buf, length ); - if ( result != length ) { + if ( result != length ) + { SG_LOG( SG_IO, SG_INFO, "Warning: read() not enough bytes." ); } @@ -310,92 +232,74 @@ int SGSocket::read( char *buf, int length ) { // read a line of data, length is max size of input buffer -int SGSocket::readline( char *buf, int length ) { - if ( sock == INVALID_SOCKET ) { +int +SGSocket::readline( char *buf, int length ) +{ + if (sock.getHandle() == -1 && + (client == 0 || client->getHandle() == -1)) + { return 0; } - // cout << "sock = " << sock << endl; - - // check for potential input - fd_set ready; - FD_ZERO(&ready); - FD_SET(sock, &ready); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - // test for any input read on sock (returning immediately, even if // nothing) - int result = select(32, &ready, 0, 0, &tv); - // cout << "result = " << result << endl; + int result = this->poll(); - if ( FD_ISSET(sock, &ready) ) { - // cout << "fd change state\n"; + if (result > 0) + { // read a chunk, keep in the save buffer until we have the // requested amount read - if ( sock_style == SOCK_STREAM ) { - // cout << "sock_stream\n"; - if ( msgsock == INVALID_SOCKET ) { - // cout << "msgsock == invalid\n"; - msgsock = sock; - sock = accept(msgsock, 0, 0); - } else { - // cout << "ready to read\n"; - char *buf_ptr = save_buf + save_len; - result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - - save_len ); - // cout << "read result = " << result << endl; - - if ( result > 0 ) { - first_read = true; - } - - save_len += result; - - // Try and detect that the remote end died. This - // could cause problems so if you see connections - // dropping for unexplained reasons, LOOK HERE! - if ( result == 0 && save_len == 0 && first_read == true ) { - SG_LOG( SG_IO, SG_ALERT, - "Connection closed by foreign host." ); - close(); - } + if (is_tcp) + { + char *buf_ptr = save_buf + save_len; + result = client->recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len ); + + if ( result > 0 ) + { + first_read = true; + } + + save_len += result; + + // Try and detect that the remote end died. This + // could cause problems so if you see connections + // dropping for unexplained reasons, LOOK HERE! + if (result == 0 && save_len == 0 && first_read == true) + { + SG_LOG( SG_IO, SG_ALERT, + "Connection closed by foreign host." ); + delete client; + client = 0; } - } else { + } + else + { char *buf_ptr = save_buf + save_len; - result = readsocket( sock, buf_ptr, SG_IO_MAX_MSG_SIZE - save_len ); + result = sock.recv( buf_ptr, SG_IO_MAX_MSG_SIZE - save_len ); save_len += result; } - - // cout << "current read = " << buf_ptr << endl; - // cout << "current save_buf = " << save_buf << endl; - // cout << "save_len = " << save_len << endl; - } else { - // cout << "no data ready\n"; } // look for the end of line in save_buf int i; - for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i ); + for ( i = 0; i < save_len && save_buf[i] != '\n'; ++i ) + ; if ( save_buf[i] == '\n' ) { result = i + 1; } else { // no end of line yet - // cout << "no eol found" << endl; return 0; } - // cout << "line length = " << result << endl; // we found an end of line // copy to external buffer strncpy( buf, save_buf, result ); buf[result] = '\0'; - // cout << "sg_socket line = " << buf << endl; - + // shift save buffer + //memmove( save_buf+, save_buf+, ? ); for ( i = result; i < save_len; ++i ) { save_buf[ i - result ] = save_buf[i]; } @@ -406,66 +310,23 @@ int SGSocket::readline( char *buf, int length ) { // write data to socket (client) -int SGSocket::write( const char *buf, const int length ) { - if ( sock == INVALID_SOCKET ) { +int +SGSocket::write( const char *buf, const int length ) +{ + netSocket* s = client == 0 ? &sock : client; + if (s->getHandle() == -1) + { return 0; } bool error_condition = false; - if ( writesocket(sock, buf, length) < 0 ) { + if ( s->send( buf, length ) < 0 ) + { SG_LOG( SG_IO, SG_ALERT, "Error writing to socket: " << port ); error_condition = true; } -#if 0 - // check for any new client connection requests - fd_set ready; - FD_ZERO(&ready); - FD_SET(sock, &ready); - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 0; - - // test for any input on sock (returning immediately, even if - // nothing) - select(32, &ready, 0, 0, &tv); - - // any new connections? - if ( FD_ISSET(sock, &ready) ) { - int msgsock = accept(sock, 0, 0); - if ( msgsock < 0 ) { - SG_LOG( SG_IO, SG_ALERT, - "Error: accept() failed in write()" ); - return 0; - } else { - client_connections.push_back( msgsock ); - } - } - - SG_LOG( SG_IO, SG_INFO, "Client connections = " << - client_connections.size() ); - for ( int i = 0; i < (int)client_connections.size(); ++i ) { - int msgsock = client_connections[i]; - - // read and junk any possible incoming messages. - // char junk[ SG_IO_MAX_MSG_SIZE ]; - // std::read( msgsock, junk, SG_IO_MAX_MSG_SIZE ); - - // write the interesting data to the socket - if ( writesocket(msgsock, buf, length) == SOCKET_ERROR ) { - SG_LOG( SG_IO, SG_ALERT, "Error writing to socket: " << port ); - error_condition = true; - } else { -#ifdef _POSIX_SYNCHRONIZED_IO - // fdatasync(msgsock); -#else - // fsync(msgsock); -#endif - } - } -#endif - if ( error_condition ) { return 0; } @@ -475,79 +336,62 @@ int SGSocket::write( const char *buf, const int length ) { // write null terminated string to socket (server) -int SGSocket::writestring( const char *str ) { - if ( sock == INVALID_SOCKET ) { - return 0; - } - +int +SGSocket::writestring( const char *str ) +{ int length = strlen( str ); - return write( str, length ); + return this->write( str, length ); } // close the port -bool SGSocket::close() { - if ( sock == INVALID_SOCKET ) { - return 0; - } +bool +SGSocket::close() +{ + delete client; + client = 0; - closesocket( sock ); - if ( sock_style == SOCK_STREAM && msgsock != INVALID_SOCKET ) { - sock = msgsock; - msgsock = INVALID_SOCKET; - } + sock.close(); return true; } // configure the socket as non-blocking -bool SGSocket::nonblock() { - if ( sock == INVALID_SOCKET ) { - return 0; +bool +SGSocket::nonblock() +{ + if (sock.getHandle() == -1) { + return false; } -#if defined(_MSC_VER) || defined(__MINGW32__) - u_long arg = 1; - if (ioctlsocket( sock, FIONBIO, &arg ) != 0) { - int error_code = WSAGetLastError(); - SG_LOG( SG_IO, SG_ALERT, - "Error " << error_code << ": unable to set non-blocking mode" -); - return false; - } -#else - fcntl( sock, F_SETFL, O_NONBLOCK ); -#endif + sock.setBlocking( false ); return true; } -#if defined(_MSC_VER) || defined(__MINGW32__) +int +SGSocket::poll() +{ + netSocket* readers[2]; + + readers[0] = client != 0 ? client : &sock; + readers[1] = 0; -bool SGSocket::wsock_init = false; + netSocket* writers[1]; + writers[0] = 0; -bool -SGSocket::wsastartup() { - WORD wVersionRequested; - WSADATA wsaData; - - //wVersionRequested = MAKEWORD( 2, 2 ); - wVersionRequested = MAKEWORD( 1, 1 ); - int err = WSAStartup( wVersionRequested, &wsaData ); - if (err != 0) + int result = netSocket::select( readers, writers, 0 ); + + if (result > 0 && is_server && client == 0) { - SG_LOG( SG_IO, SG_ALERT, "Error: Couldn't load winsock" ); - return false; + // Accept a new client connection + netAddress addr; + int new_fd = sock.accept( &addr ); + SG_LOG( SG_IO, SG_INFO, "Accepted connection from " + << addr.getHost() << ":" << addr.getPort() ); + client = new netSocket(); + client->setHandle( new_fd ); + return 0; } -#if 0 - if ( LOBYTE( wsaData.wVersion ) != 2 || - HIBYTE( wsaData.wVersion ) != 2 ) { - SG_LOG( SG_IO, SG_ALERT, "Couldn't load a suitable winsock"); - WSACleanup( ); - return false; - } -#endif - wsock_init = true; - return true; + return result; } -#endif diff --git a/simgear/io/sg_socket.hxx b/simgear/io/sg_socket.hxx index 7c98257d..4e1d9e05 100644 --- a/simgear/io/sg_socket.hxx +++ b/simgear/io/sg_socket.hxx @@ -39,11 +39,9 @@ #include #include -SG_USING_STD(string); +#include -#if defined(_MSC_VER) || defined(__MINGW32__) -# include -#endif +SG_USING_STD(string); #define SG_MAX_SOCKET_QUEUE 32 @@ -53,13 +51,6 @@ SG_USING_STD(string); */ class SGSocket : public SGIOChannel { public: -#if defined(_MSC_VER) || defined(__MINGW32__) - typedef SOCKET SocketType; -#else - typedef int SocketType; -# define INVALID_SOCKET (-1) -#endif - private: string hostname; string port_str; @@ -67,31 +58,23 @@ private: char save_buf[ 2 * SG_IO_MAX_MSG_SIZE ]; int save_len; - SocketType sock; - SocketType msgsock; - short unsigned int port; - int sock_style; // SOCK_STREAM or SOCK_DGRAM - + netSocket sock; + netSocket* client; + unsigned short port; + bool is_tcp; + bool is_server; bool first_read; + static bool init; + // make a server (master listening) socket - SocketType make_server_socket(); + bool make_server_socket(); // make a client socket - SocketType make_client_socket(); + bool make_client_socket(); - // wrapper functions - int readsocket( int fd, void *buf, size_t count ); - int writesocket( int fd, const void *buf, size_t count ); -#if !defined(_MSC_VER) && !defined(__MINGW32__) - int closesocket(int fd); -#endif - -#if defined(_MSC_VER) || defined(__MINGW32__) - // Ensure winsock has been initialised. - static bool wsock_init; - static bool wsastartup(); -#endif + // Poll for new connections or data to read. + int poll(); public: diff --git a/simgear/io/tcp_client.cxx b/simgear/io/tcp_client.cxx new file mode 100644 index 00000000..a902bb12 --- /dev/null +++ b/simgear/io/tcp_client.cxx @@ -0,0 +1,77 @@ +#include +#include + +#include + +#include "sg_socket.hxx" + +using std::cout; + +class TcpClient +{ +public: + TcpClient( const char* host, const char* port ); + ~TcpClient(); + + bool open(); + bool process(); + bool close(); + +private: + SGIOChannel* channel; +}; + +TcpClient::TcpClient( const char* host, const char* port ) +{ + channel = new SGSocket( host, port, "tcp" ); +} + +TcpClient::~TcpClient() +{ + delete channel; +} + +bool +TcpClient::open() +{ + return channel->open( SG_IO_OUT ); +} + +bool +TcpClient::process() +{ + char wbuf[1024]; + + sprintf( wbuf, "hello world\n" ); + int length = channel->writestring( wbuf ); + cout << "writestring returned " << length << "\n"; + + return true; +} + +bool +TcpClient::close() +{ + return channel->close(); +} + +int +main() +{ + sglog().setLogLevels( SG_ALL, SG_INFO ); + TcpClient client( "localhost", "5500" ); + if (!client.open()) + { + cout << "client open failed\n"; + return 0; + } + + for (int i = 0; i < 3; ++i) + { + client.process(); + sleep(1); + } + + //client.close(); + return 0; +} diff --git a/simgear/io/tcp_server.cxx b/simgear/io/tcp_server.cxx new file mode 100644 index 00000000..ac7abddc --- /dev/null +++ b/simgear/io/tcp_server.cxx @@ -0,0 +1,69 @@ +#include +#include +#include + +#include "sg_socket.hxx" + +using std::string; +using std::cout; + +class TcpServer +{ +public: + TcpServer(); + bool open(); + bool process(); + bool close(); + +private: + SGIOChannel* channel; +}; + +TcpServer::TcpServer() +{ + channel = new SGSocket( "", "5500", "tcp" ); +} + +bool +TcpServer::open() +{ + channel->open( SG_IO_BI ); + return true; +} + +bool +TcpServer::process() +{ + char buf[1024]; + + int len; + while ((len = channel->readline( buf, sizeof(buf) )) > 0) + { + cout << len << ": " << buf; + } + return true; +} + +bool +TcpServer::close() +{ + return channel->close(); +} + + +int +main() +{ + sglog().setLogLevels( SG_ALL, SG_INFO ); + TcpServer server; + server.open(); + SG_LOG( SG_IO, SG_INFO, "Created TCP server" ); + + while (1) + { + server.process(); + } + + server.close(); + return 0; +} -- 2.39.2