Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 200 lines (163 sloc) 3.64 KB
#ifndef com_sleepless_blocksocket_cpp
#define com_sleepless_blocksocket_cpp
// Copyright 2004 Sleepless Software Inc. All Rights Reserved
#include "socket.cpp"
/* A BlockSocket is just like a normal socket, except that it sends
data over the wire in blocks.
When you do a write of a buffer, what is actually sent, is a 4-byte
length in network byte order, followed by the actual buffer contents.
This makes it very simple and easy to read and write simple messages
over a socket. You don't have to scan every byte while reading, looking
for a newline or null to terminate a line, for example, and the
code to read and write is very simple.
*/
struct BlockSocket
{
Socket *sock;
bool isConnected()
{
if(sock)
return sock->isConnected();
return false;
}
/* Returns the # of bytes written (not counting block len header)
or -1 on error. For example, if you pass a 'len' of 10 bytes,
then 10 will be returned for a successful write, even though
14 bytes actually went over the wire. */
int write(const char *buf, unsigned int len)
{
if(isConnected())
{
unsigned int l = htonl(len);
int r = sock->write((char *)&l, 4);
if(r == 4)
{
r = sock->write(buf, len);
return r;
}
}
return -1;
}
int read(char *buf, unsigned int len, unsigned int *ep)
{
if(isConnected())
{
unsigned int l;
int r = sock->read((char *)&l, 4);
if(r == 4)
{
l = ntohl(l);
if(l <= len)
{
r = sock->read(buf, l);
return r;
}
else
{
if(ep)
*ep = l;
}
// overrun ... msg won't fit in buffer provided
}
}
return -1;
}
/* Reads a block from the socket.
Returns -1 if the socket isn't connected
Returns -1 if there was an IO error
Returns -1 if the block msg written to the socket on the other end
is too big to fit into the buffer provided.
Otherwise, reads the block into buf, and returns it's length
Note: If -1 is returned for any reason, the BlockSocket is
incapable of performing any further reads successfully. */
int read(char *buf, unsigned int len)
{
unsigned int ep;
return read(buf, len, &ep);
}
BlockSocket(const char *host, int port)
{
sock = new Socket(host, port);
}
BlockSocket(Socket *s)
{
sock = s;
}
~BlockSocket()
{
if(sock)
delete sock;
}
};
#ifdef MAIN_TEST
#include "ServerSocket.cpp"
int port = 12345;
int main(int argc, char **argv)
{
if(argc < 2)
return 1;
if(argv[1][0] == 's')
{
// be server
ServerSocket ss(port, 5);
if(ss.isListening())
{
printf("server: listening on port %d\n", port);
Socket *sock = ss.accept();
printf("server: connection received from %s\n", sock->remoteIP);
BlockSocket bs(sock);
while(true)
{
char buf[1000];
int r = bs.read(buf, sizeof(buf));
if(r < 1)
{
break;
}
printf("received: %s\n", buf);
buf[0] = 'X';
printf("returning: %s\n", buf);
int w = bs.write(buf, r);
if(w != r)
{
printf("server: sock write error\n");
break;
}
}
printf("server: done\n");
}
}
else
{
BlockSocket bs("localhost", port);
if(bs.isConnected())
{
printf("client: connected to port %d\n", port);
char buf[1000];
while(true)
{
printf("Enter something: "); fflush(stdout);
if(!fgets(buf, sizeof(buf), stdin))
break;
int l = strlen(buf);
buf[l - 1] = 0;
int w = bs.write(buf, l);
if(w != l)
{
printf("client: sock write error\n");
break;
}
int r = bs.read(buf, sizeof(buf));
if(r < 1)
{
printf("client: sock read error\n");
break;
}
printf("Response: %s\n", buf);
}
printf("\n");
}
}
}
#endif
#endif // com_sleepless_blocksocket_cpp