cpp utils files, network and a smal util class
This commit is contained in:
parent
ea3dffdb4a
commit
62f50a2f79
13 changed files with 610 additions and 0 deletions
27
net/serversocket.cpp
Normal file
27
net/serversocket.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#include "serversocket.h"
|
||||
using namespace zutil;
|
||||
|
||||
|
||||
ServerSocket::ServerSocket( int port ){
|
||||
if ( !SocketIO::create() ){
|
||||
throw SocketException ( "Could not create server socket." );
|
||||
}
|
||||
if ( !Socket::bind( port ) ){
|
||||
throw SocketException ( "Could not bind to port." );
|
||||
}
|
||||
if ( !Socket::listen() ){
|
||||
throw SocketException ( "Could not listen to socket." );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Socket* ServerSocket::accept( ){
|
||||
Socket *sock = new Socket();
|
||||
accept(*sock);
|
||||
return sock;
|
||||
}
|
||||
void ServerSocket::accept( Socket& sock ){
|
||||
if ( !SocketIO::accept( sock ) ){
|
||||
throw SocketException ( "Could not accept socket." );
|
||||
}
|
||||
}
|
||||
18
net/serversocket.h
Normal file
18
net/serversocket.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef ZUTIL_NET_SERVERSOCKET
|
||||
#define ZUTIL_NET_SERVERSOCKET
|
||||
|
||||
#include "socket.h"
|
||||
using namespace std;
|
||||
|
||||
namespace zutil{
|
||||
class ServerSocket : protected Socket{
|
||||
public:
|
||||
ServerSocket( int port );
|
||||
virtual ~ServerSocket(){};
|
||||
|
||||
Socket* accept( );
|
||||
void accept( Socket& );
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
69
net/socket.cpp
Normal file
69
net/socket.cpp
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#include "socket.h"
|
||||
using namespace zutil;
|
||||
|
||||
Socket::Socket(){
|
||||
streambuf = NULL;
|
||||
in = NULL;
|
||||
out = NULL;
|
||||
}
|
||||
Socket::Socket( string host, int port ){
|
||||
streambuf = NULL;
|
||||
in = NULL;
|
||||
out = NULL;
|
||||
|
||||
if ( !SocketIO::create() ){
|
||||
throw SocketException ( "Could not create client socket." );
|
||||
}
|
||||
|
||||
if ( !SocketIO::connect ( host, port ) ){
|
||||
throw SocketException ( "Could not bind to port." );
|
||||
}
|
||||
}
|
||||
Socket::~Socket(){
|
||||
delete in;
|
||||
delete out;
|
||||
delete streambuf;
|
||||
}
|
||||
|
||||
istream& Socket::get_istream(){
|
||||
if(streambuf == NULL)
|
||||
streambuf = new SocketStreamBuffer( *this );
|
||||
if(in == NULL)
|
||||
in = new istream( streambuf );
|
||||
return *in;
|
||||
}
|
||||
ostream& Socket::get_ostream(){
|
||||
if(streambuf == NULL)
|
||||
streambuf = new SocketStreamBuffer( *this );
|
||||
if(out == NULL)
|
||||
out = new ostream( streambuf );
|
||||
return *out;
|
||||
}
|
||||
|
||||
|
||||
const Socket& Socket::operator<<( const string &s ) const{
|
||||
if ( !SocketIO::write( s ) ){
|
||||
throw SocketException ( "Could not write string to socket." );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
const Socket& Socket::operator<<( const char c ) const{
|
||||
if ( !SocketIO::write( c ) ){
|
||||
throw SocketException ( "Could not write char to socket." );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
const Socket& Socket::operator>>( string &s ) const{
|
||||
if ( !SocketIO::read( s ) ){
|
||||
throw SocketException ( "Could not read string from socket." );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
const Socket& Socket::operator>>( char &c ) const{
|
||||
if ( !(c = SocketIO::read( )) ){
|
||||
throw SocketException ( "Could not read char from socket." );
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
30
net/socket.h
Normal file
30
net/socket.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef ZUTIL_NET_SOCKET
|
||||
#define ZUTIL_NET_SOCKET
|
||||
|
||||
#include "socketio.h"
|
||||
#include "socketexception.h"
|
||||
#include "socketstream.h"
|
||||
using namespace std;
|
||||
|
||||
namespace zutil{
|
||||
class Socket : public SocketIO{
|
||||
protected:
|
||||
SocketStreamBuffer *streambuf;
|
||||
istream *in;
|
||||
ostream *out;
|
||||
public:
|
||||
Socket( string host, int port );
|
||||
explicit Socket();
|
||||
virtual ~Socket();
|
||||
|
||||
istream& get_istream();
|
||||
ostream& get_ostream();
|
||||
|
||||
const Socket& operator<<( const string& ) const;
|
||||
const Socket& operator<<( const char ) const;
|
||||
const Socket& operator>>( string& ) const;
|
||||
const Socket& operator>>( char& ) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
22
net/socketexception.h
Normal file
22
net/socketexception.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef SOCKETEXCEPTION
|
||||
#define SOCKETEXCEPTION
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
namespace zutil{
|
||||
class SocketException{
|
||||
public:
|
||||
SocketException(const string &s ) : msg(s) {};
|
||||
~SocketException(){};
|
||||
|
||||
string description() const{
|
||||
return msg;
|
||||
}
|
||||
|
||||
private:
|
||||
const string msg;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
151
net/socketio.cpp
Normal file
151
net/socketio.cpp
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
#include "socketio.h"
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
using namespace zutil;
|
||||
|
||||
SocketIO::SocketIO() : socket_id(-1){
|
||||
memset( &address, 0, sizeof( address ) );
|
||||
}
|
||||
|
||||
SocketIO::~SocketIO(){
|
||||
if( is_valid() )
|
||||
close( socket_id );
|
||||
}
|
||||
|
||||
bool SocketIO::create(){
|
||||
socket_id = socket( AF_INET, SOCK_STREAM, 0 );
|
||||
|
||||
if( !is_valid() )
|
||||
return false;
|
||||
|
||||
|
||||
// TIME_WAIT - argh
|
||||
int on = 1;
|
||||
if( setsockopt( socket_id, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on) ) == -1 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SocketIO::bind( const int port ){
|
||||
if ( !is_valid() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = INADDR_ANY;
|
||||
address.sin_port = htons( port );
|
||||
|
||||
int bind_return = ::bind( socket_id, (struct sockaddr*)&address, sizeof( address ) );
|
||||
|
||||
if( bind_return == -1 ){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SocketIO::listen() const{
|
||||
if ( !is_valid() ){
|
||||
return false;
|
||||
}
|
||||
|
||||
int listen_return = ::listen( socket_id, MAX_CONNECTIONS );
|
||||
|
||||
if ( listen_return == -1 ){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SocketIO::accept( SocketIO& new_socket ) const{
|
||||
int addr_length = sizeof( address );
|
||||
new_socket.socket_id = ::accept( socket_id, (sockaddr*)&address, (socklen_t*) &addr_length );
|
||||
|
||||
if( new_socket.socket_id <= 0 )
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SocketIO::write( const char c ) const{
|
||||
return write( &c, 1 );
|
||||
}
|
||||
bool SocketIO::write( const string s ) const{
|
||||
return write( s.c_str(), s.size() );
|
||||
}
|
||||
bool SocketIO::write( const char* buf, size_t len ) const{
|
||||
int sent_bytes = send( socket_id, buf, len, MSG_PRIO);
|
||||
if ( sent_bytes == -1 )
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
char SocketIO::read( ) const{
|
||||
char c;
|
||||
read( &c, 1 );
|
||||
return c;
|
||||
}
|
||||
int SocketIO::read( string &s ) const{
|
||||
s = "";
|
||||
char buf [ SOCKET_BUFFER + 1 ];
|
||||
|
||||
int recv_bytes = read( buf, SOCKET_BUFFER );
|
||||
if(recv_bytes > 0)
|
||||
s = buf;
|
||||
return recv_bytes;
|
||||
}
|
||||
int SocketIO::read( char* buf, size_t len ) const{
|
||||
memset( buf, 0, len );
|
||||
int recv_bytes = recv( socket_id, buf, len, 0 );
|
||||
|
||||
if( recv_bytes == -1 ){
|
||||
cout << "status == -1 errno == " << errno << " in Socket::read\n";
|
||||
return 0;
|
||||
}
|
||||
else if( recv_bytes == 0 ){
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
return recv_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
bool SocketIO::connect( const string host, const int port ){
|
||||
if ( !is_valid() ) return false;
|
||||
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_port = htons( port );
|
||||
|
||||
int status = inet_pton( AF_INET, host.c_str(), &address.sin_addr );
|
||||
|
||||
if ( errno == EAFNOSUPPORT )
|
||||
return false;
|
||||
|
||||
status = ::connect( socket_id, (sockaddr*)&address, sizeof ( address ) );
|
||||
|
||||
if( status == 0 )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void SocketIO::set_non_blocking( const bool b ){
|
||||
int opts;
|
||||
opts = fcntl( socket_id, F_GETFL );
|
||||
|
||||
if( opts < 0 ){
|
||||
return;
|
||||
}
|
||||
|
||||
if( b )
|
||||
opts = ( opts | O_NONBLOCK );
|
||||
else
|
||||
opts = ( opts & ~O_NONBLOCK );
|
||||
|
||||
fcntl ( socket_id, F_SETFL,opts );
|
||||
|
||||
}
|
||||
53
net/socketio.h
Normal file
53
net/socketio.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef ZUTIL_NET_SOCKET_IO
|
||||
#define ZUTIL_NET_SOCKET_IO
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <string>
|
||||
#include "socketexception.h"
|
||||
using namespace std;
|
||||
|
||||
//const int MAXHOSTNAME = 200;
|
||||
const int MAX_CONNECTIONS = 5;
|
||||
const int SOCKET_BUFFER = 500;
|
||||
const int MSG_PRIO = 0; // defined by dgame
|
||||
|
||||
namespace zutil{
|
||||
class SocketIO{
|
||||
private:
|
||||
int socket_id;
|
||||
sockaddr_in address;
|
||||
public:
|
||||
SocketIO();
|
||||
virtual ~SocketIO();
|
||||
|
||||
// Server initialization
|
||||
bool create();
|
||||
bool bind( const int port );
|
||||
bool listen() const;
|
||||
bool accept( SocketIO& ) const;
|
||||
|
||||
// Client initialization
|
||||
bool connect( const string host, const int port );
|
||||
|
||||
// Data Transimission
|
||||
bool write( const char c ) const;
|
||||
bool write( const string ) const;
|
||||
bool write( const char* buf, const size_t len ) const;
|
||||
|
||||
char read( ) const;
|
||||
int read( string& ) const;
|
||||
int read( char* buf, const size_t len ) const;
|
||||
|
||||
|
||||
void set_non_blocking( const bool );
|
||||
bool is_valid() const { return socket_id != -1; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
47
net/socketstream.cpp
Normal file
47
net/socketstream.cpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#include "socketstream.h"
|
||||
using namespace zutil;
|
||||
|
||||
SocketStreamBuffer::SocketStreamBuffer(SocketIO &s) : soc(s){
|
||||
pBeg = pBuffer;
|
||||
pCur = pBuffer;
|
||||
pEnd = pBuffer;
|
||||
//pEnd = pBuffer + BUFFER_SIZE;
|
||||
streambuf::setp(pBeg, pEnd);
|
||||
|
||||
gBeg = gBuffer;
|
||||
gCur = gBuffer;
|
||||
gEnd = gBuffer + BUFFER_SIZE;
|
||||
streambuf::setg(gBeg, gCur, gEnd);
|
||||
}
|
||||
|
||||
int SocketStreamBuffer::underflow() {
|
||||
int recv_bytes = soc.read(gBuffer, BUFFER_SIZE);
|
||||
|
||||
if(recv_bytes > 0){
|
||||
gCur = gBuffer;
|
||||
gEnd = gBuffer+recv_bytes;
|
||||
streambuf::setg(gBeg, gCur, gEnd);
|
||||
|
||||
return Tr::not_eof( *gCur );
|
||||
}
|
||||
return Tr::eof();
|
||||
}
|
||||
|
||||
int SocketStreamBuffer::overflow(int c) {
|
||||
if(c == Tr::eof())
|
||||
return Tr::not_eof(c);
|
||||
soc.write(c);
|
||||
return c;
|
||||
/*if(sync() >= 0)
|
||||
return c;
|
||||
return Tr::eof();*/
|
||||
}/*
|
||||
int SocketStreamBuffer::sync() {
|
||||
if( soc.write( pBuffer, pCur-pBeg )){
|
||||
pCur = pBuffer;
|
||||
streambuf::setp(pBeg, pEnd);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}*/
|
||||
|
||||
36
net/socketstream.h
Normal file
36
net/socketstream.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef ZUTIL_NET_SOCKETSTREAM
|
||||
#define ZUTIL_NET_SOCKETSTREAM
|
||||
|
||||
#include <iostream>
|
||||
#include "socketio.h"
|
||||
using namespace std;
|
||||
|
||||
const size_t BUFFER_SIZE = 100;
|
||||
|
||||
namespace zutil{
|
||||
class SocketStreamBuffer : public streambuf{
|
||||
private:
|
||||
SocketIO &soc;
|
||||
|
||||
char pBuffer[BUFFER_SIZE];
|
||||
char gBuffer[BUFFER_SIZE];
|
||||
char *pBeg, *pCur, *pEnd;
|
||||
char *gBeg, *gCur, *gEnd;
|
||||
|
||||
typedef char_traits<char> Tr;
|
||||
protected:
|
||||
//virtual int uflow();
|
||||
virtual int underflow();
|
||||
//virtual streamsize xsgetn(char_type *s, streamsize n);
|
||||
|
||||
virtual int overflow(int = Tr::eof());
|
||||
//virtual streamsize xsputn(const char_type *s, streamsize n);
|
||||
//virtual int sync();
|
||||
|
||||
public:
|
||||
SocketStreamBuffer(SocketIO &s);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
24
net/test_client.cpp
Normal file
24
net/test_client.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include "socket.h"
|
||||
#include "socketexception.h"
|
||||
using namespace std;
|
||||
|
||||
int main ( int argc, int argv[] ){
|
||||
try{
|
||||
Socket socket ( "localhost", 30000 );
|
||||
std::string reply;
|
||||
|
||||
try{
|
||||
socket << "Test message.";
|
||||
socket >> reply;
|
||||
}
|
||||
catch ( SocketException& ) {}
|
||||
cout << "We received this response from the server:\n\"" << reply << "\"\n";
|
||||
|
||||
}catch ( SocketException& e ){
|
||||
cout << "Exception was caught:" << e.description() << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
37
net/test_server.cpp
Normal file
37
net/test_server.cpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include "socket.h"
|
||||
#include "serversocket.h"
|
||||
#include "socketexception.h"
|
||||
using namespace std;
|
||||
using namespace zutil;
|
||||
|
||||
int main ( int argc, int argv[] ){
|
||||
cout << "running....\n";
|
||||
|
||||
try{
|
||||
// Create the socket
|
||||
ServerSocket server ( 30000 );
|
||||
|
||||
while ( true ){
|
||||
Socket new_sock;
|
||||
server.accept ( new_sock );
|
||||
|
||||
istream &in = new_sock.get_istream();
|
||||
ostream &out = new_sock.get_ostream();
|
||||
|
||||
try{
|
||||
while ( true ){
|
||||
string data;
|
||||
in >> data;
|
||||
cout << data << endl;
|
||||
out << data;
|
||||
}
|
||||
}catch ( SocketException& ) {}
|
||||
}
|
||||
}catch ( SocketException& e ){
|
||||
cout << "Exception was caught:" << e.description() << "\nExiting.\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
48
util.cpp
Normal file
48
util.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include "util.h"
|
||||
|
||||
|
||||
void zutil::tolower(string &s){
|
||||
for(size_t i=0; s[i] ;++i){
|
||||
s[i] = std::tolower(s[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void zutil::trim(string &str){
|
||||
size_t s = str.find_first_not_of(" \n\r\t");
|
||||
size_t e = str.find_last_not_of (" \n\r\t");
|
||||
|
||||
if( string::npos != s && string::npos != e)
|
||||
str = str.substr(s, e-s+1);
|
||||
}
|
||||
|
||||
|
||||
vector<string> zutil::parseLine(istream &in, char separator, char endl){
|
||||
vector<string> parsed;
|
||||
string line;
|
||||
getline(in, line, endl);
|
||||
|
||||
return split( line, separator );
|
||||
}
|
||||
|
||||
vector<string> zutil::split(const string &line, char separator){
|
||||
vector<string> parsed;
|
||||
|
||||
string tmp;
|
||||
for(size_t i=0; i<line.length() ;++i){
|
||||
if(line[i] == separator && !tmp.empty()){
|
||||
parsed.push_back( tmp );
|
||||
tmp = "";
|
||||
}
|
||||
else{
|
||||
tmp += line[i];
|
||||
}
|
||||
}
|
||||
if(!tmp.empty()){
|
||||
parsed.push_back( tmp );
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
48
util.h
Normal file
48
util.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef ZUTIL
|
||||
#define ZUTIL
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <cctype>
|
||||
using namespace std;
|
||||
|
||||
|
||||
namespace zutil{
|
||||
|
||||
void tolower(string &s);
|
||||
void trim(string &str);
|
||||
vector<string> parseLine(istream &in, char separator, char endl);
|
||||
vector<string> split(const string &s, char separator);
|
||||
|
||||
template<typename T>
|
||||
bool remove(vector<T> &v, const T &item){
|
||||
typename vector<T>::iterator it;
|
||||
it = find(v.begin(), v.end(), item);
|
||||
|
||||
if(it != v.end()){
|
||||
v.erase(it);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool contains(const vector<T> &v, const T &item){
|
||||
typename vector<T>::const_iterator it;
|
||||
it = find(v.begin(), v.end(), item);
|
||||
if(it != v.end())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
string to_string(const T &t){
|
||||
stringstream ss;
|
||||
ss << t;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue