C++ iostream socket.
Posted: Wed Feb 11, 2004 10:50 pm
Here's a little something for anyone working with sockets in C++. I needed an iostream to access a socket. The correct way to do this is to implement a subclass of stream_buf. Scanning the net I found a number of large C++ socket libraries, but no bare bones examples. I did find some examples of either bad examples or GPL code.
So this is just a very simple example of where to start released into the public domain. Do as you please with it. It still needs some work, so if you make improvements, it would be nice to reply here or publish as public domain aswell.
Oobles.
So this is just a very simple example of where to start released into the public domain. Do as you please with it. It still needs some work, so if you make improvements, it would be nice to reply here or publish as public domain aswell.
Oobles.
Code: Select all
// Created by David Ryan.
// Released into public domain Feb 2004.
// Please improve and set free again.
using namespace std;
#include <streambuf>
#include <iostream>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#ifndef TIOCINQ
#define TIOCINQ FIONREAD
#endif
class socket_buf : public streambuf
{
private:
int _socket;
char _inBuffer[1024];
char _outBuffer[1024];
public:
socket_buf( int socket )
{
_socket = socket;
setg( _inBuffer, _inBuffer, _inBuffer );
setp( _outBuffer, _outBuffer+1024 );
}
protected:
int overflow(int x)
{
cout << "socket_buf::overflow()" << x << endl;
return x;
}
int sync()
{
cout << "socket_buf::sync()" << endl;
// if no data availalbe just return.
if ( pbase() == pptr() )
return 0;
// try and send the data.
int len = pptr() - pbase();
int rc = send( _socket, pbase(), len, 0 );
if ( rc < 0 )
return rc;
setp( _outBuffer, _outBuffer+1024 );
return 0;
}
int underflow()
{
cout << "socket_buf::underflow() " << endl;
if (gptr () < egptr ()) return *(unsigned char*)gptr ();
int len;
// find out how much data is available.
if( ioctl( _socket, TIOCINQ, &len) < 0 )
{
// error
cout << "socket_buf error" << endl;
len = 1;
}
// make sure length is atleast 1. We will block.
if ( len == 0 )
len = 1;
// try and read in some data.
int read = recv( _socket, &_inBuffer, len, 0 );
if ( read > 0 )
{
setg( _inBuffer, _inBuffer, _inBuffer+read );
}
else
{
return EOF;
}
return *(unsigned char*)gptr ();
}
};
class siostream: public iostream
{
private:
socket_buf _buf;
public:
siostream( int socket )
:_buf( socket ), iostream( &_buf )
{
}
};
int main( int argc, char *argv[] )
{
int port = 95;
cout << "test socket" << endl;
struct hostent *he=gethostbyname(argv[1]);
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = PF_INET;
sa.sin_addr = *((struct in_addr *)he->h_addr);
sa.sin_port = htons(port);
int s = socket(AF_INET, SOCK_STREAM, 0);
int rv = connect( s, (struct sockaddr*) &sa, sizeof(sa) );
cout << "connect = " << rv << endl;
siostream sock( s );
sock << "23" << endl;
sock.flush();
cout << "got =" << sock.get() << endl;
cout << "finished" << endl;
}