cpp utils files, network and a smal util class

This commit is contained in:
Ziver Koc 2009-11-21 01:11:05 +00:00
parent ea3dffdb4a
commit 62f50a2f79
13 changed files with 610 additions and 0 deletions

27
net/serversocket.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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