So I’ve been working on this project that heavily uses Sockets in C++, for the base of this project I’ve created a TCP Socket class so I concentrate on the protocol I’m using rather than worrying about the socket itself and I thought I would share this class with your.
so here it is:
Download Class
Header
//tcpCase.h
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#ifndef TCPCASE_H_
#define TCPCASE_H_
class tcpCase
{
public:
tcpCase(char * _port, char * _addr);
virtual ~tcpCase();
void startConnection();
bool charSearch(char *toSearch, char *searchFor);
private:
addrinfo hints, *servinfo;
char *addr;
char *port;
int s; //the socket descriptor
bool sendData(char *msg);
void manageRecv(int numbytes, char * buf);
};
#endif /* TCPCASE_H_ */
Class
//tcpCase.cpp
#include "tcpCase.h"
using namespace std;
#define MAXDATASIZE 100
tcpCase::tcpCase(char * _port, char * _addr)
{
port = _port;
addr = _addr;
//Ensure that servinfo is clear
memset(&hints, 0, sizeof hints); // make sure the struct is empty
//setup hints
hints.ai_family = AF_UNSPEC; // don't care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
//Setup the structs if error print why
int res;
if ((res = getaddrinfo(addr,port,&hints,&servinfo)) != 0)
{
fprintf(stderr,"getaddrinfo: %s\n", gai_strerror(res));
}
//setup the socket
if ((s = socket(servinfo->ai_family,servinfo->ai_socktype,servinfo->ai_protocol)) == -1)
{
perror("client: socket");
}
}
tcpCase::~tcpCase()
{
// TODO Auto-generated destructor stub
}
void tcpCase::startConnection()
{//This goes into the send/rcv loop
//Connect
if (connect(s,servinfo->ai_addr, servinfo->ai_addrlen) == -1)
{
close (s);
perror("Client Connect");
}
//We dont need this anymore
freeaddrinfo(servinfo);
int numbytes;
char buf[MAXDATASIZE];
while (1)
{
//Recv & print Data
numbytes = recv(s,buf,MAXDATASIZE-1,0);
buf[numbytes]='\0';
cout << buf;
//What do I do with the recived data
manageRecv(numbytes,buf);
//break if connection closed
if (numbytes==0)
{
cout << "----------------------CONNECTION CLOSED---------------------------"<< endl;
break;
}
}
}
bool tcpCase::charSearch(char *toSearch, char *searchFor)
{
int len = strlen(toSearch);
int forLen = strlen(searchFor); // The length of the searchfor field
//Search through each char in toSearch
for (int i = 0; i < len;i++)
{
//If the active char is equil to the first search item then search toSearch
if (searchFor[0] == toSearch[i])
{
bool found = true;
//search the char array for search field
for (int x = 1; x < forLen; x++)
{
if (toSearch[i+x]!=searchFor[x])
{
found = false;
}
}
//if found return true;
if (found == true)
return true;
}
}
return 0;
}
bool tcpCase::sendData(char *msg)
{//Send some data
//Send some data
int len = strlen(msg);
int bytes_sent = send(s,msg,len,0);
if (bytes_sent == 0)
return false;
else
return true;
}
void tcpCase::manageRecv(int numbytes, char * buf)
{
/*
* TODO: Add your code here!
* int numbytes: this is the number of bytes in the recived msg
* char * buf: this is the message recieved
*/
}
Download Class
To use this class edit the manageRecv() to fit to the protocol you wish to use, this function is called every time a new message is received. You get the variables:
- int numbytes : the number of bytes in the recived message
- char * buf : the message recived
from this you should be able to program your protocol.
Calling this class is also pretty simple, all you need to do is give the parameters:
- port: the port you want to connect to
- addr: the server you want to connect to
then call the startConnection() function to get the client to connect, here is a quick example:
tcpCase test = tcpCase("6667","irc.ubuntu.com");
test.startConnection();
If you want more information on c++ socket programming I recommend you read Beej’s Guide to Network Programming. As socket programming is a complicated thing i recommend you read the whole of this great guide, rather then just skipping to the the examples (learn from my mistake there)


