I wrote a TCP Socket C++ socket class years ago for a SGI, REDHAT and Windows machines.
I removed the SGI code. So, hopefully I didn't mess anything up.
REDHAT should work for a Linux machine.
tcpSocket.h:
#ifndef __TCPSOCKET_H
#define __TCPSOCKET_H
#ifdef REDHAT
#define INVALID_SOCKET -1
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#if !defined(TRUE) || ((TRUE) != 1)
#define TRUE (1)
#endif
#if !defined(FALSE) || ((FALSE) != 0)
#define FALSE (0)
#endif
#endif
#ifdef WIN32
#include <stdio.h>
#include <winsock2.h>
#endif
class tcpSocket {
public:
tcpSocket();
~tcpSocket();
int openClient(unsigned short port, char *addr);
int openServer(unsigned short port, char *addr);
void checkSocket(void);
void closeSocket(void);
// WRITE MESSAGE
// Return: -1=Error writing message, >0=Number bytes written
int writeMsg(char *msg, int size);
// READ MESSAGE
// Return: -1=Error reading message, 0=No message, >0=Number bytes read
int readMsg(char *msg, int maxSize);
int peek(char *msg, int size);
private:
#ifdef REDHAT
int sock;
int sockServer;
struct sockaddr_in local, to;
#endif
#ifdef WIN32
SOCKET sock;
SOCKET sockServer;
struct sockaddr_in local, to;
#endif
};
#endif
tcpSocket.cpp:
#include "tcpSocket.h"
//--------------------------------------------------------------------------------
tcpSocket::tcpSocket()
{
sock = INVALID_SOCKET;
sockServer = INVALID_SOCKET;
}
//--------------------------------------------------------------------------------
tcpSocket::~tcpSocket()
{
}
//--------------------------------------------------------------------------------
int tcpSocket::openClient(unsigned short port, char *addr)
{
if (port == 0) return TRUE;
#ifdef REDHAT
int flags;
int on=1;
if (sock == INVALID_SOCKET) {
bzero(&to, sizeof(to));
to.sin_family = AF_INET;
to.sin_port = htons( port );
to.sin_addr.s_addr = inet_addr( addr );
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
printf("ERROR - Unable to create socket\n");
return TRUE;
}
// Enable Address Reuse
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
// Enable No_Delay
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
if ( connect(sock, (const sockaddr*)&to, sizeof(to)) == -1 ) {
printf("ERROR - Unable to connect to socket\n");
return TRUE;
}
// Enable Non-blocking I/O
flags = fcntl(sock, F_GETFL, 0);
if ( fcntl(sock, F_SETFL, flags | FNONBLOCK) == -1 ) {
printf("ERROR - Unable to set as nonblocking socket\n");
return TRUE;
}
}
return FALSE;
#endif
#ifdef WIN32
int stat;
int on=1;
unsigned long onl=1;
WSADATA wsaData;
if (sock == INVALID_SOCKET) {
if ( WSAStartup( 0x202, &wsaData ) == SOCKET_ERROR ) {
WSACleanup();
return TRUE;
}
sock = socket( AF_INET, SOCK_STREAM, 0 );
if ( sock < 0 ) {
printf("ERROR - Opening socket\n");
WSACleanup();
return TRUE;
}
to.sin_family = AF_INET;
to.sin_port = htons( port );
to.sin_addr.s_addr = inet_addr( addr );
// Enable Address Reuse (MUST be before the bind!)
stat = setsockopt( sock,
SOL_SOCKET,
SO_REUSEADDR,
(const char *)&on,
sizeof(on) );
if ( stat == SOCKET_ERROR ) {
printf("ERROR - Unable to enable address reuse\n");
closesocket( sock );
WSACleanup();
return TRUE;
}
stat = connect( sock,
(struct sockaddr *)&to,
sizeof(to) );
if ( stat == SOCKET_ERROR ) {
printf("ERROR - Connect to socket\n");
// fprintf(stderr,"connect() failed: %d\n",WSAGetLastError());
closesocket( sock );
WSACleanup();
return TRUE;
}
// Enable Non-blocking I/O
stat = ioctlsocket( sock,
FIONBIO,
&onl );
if ( stat == SOCKET_ERROR ) {
printf("ERROR - Unable to enable Non-blocking I/O\n");
return TRUE;
}
}
return FALSE;
#endif
}
//--------------------------------------------------------------------------------
int tcpSocket::openServer(unsigned short port, char *addr)
{
if (port == 0) return TRUE;
#ifdef REDHAT
int flags;
int on=1;
int len;
struct sockaddr_in clientAddr;
if (sockServer == INVALID_SOCKET && sock == INVALID_SOCKET) {
bzero(&local, sizeof(local));
local.sin_family = AF_INET;
local.sin_port = htons( port );
local.sin_addr.s_addr = (in_addr_t)inet_addr("0.0.0.0");
bzero(&to, sizeof(to));
to.sin_family = AF_INET;
to.sin_port = htons( port );
to.sin_addr.s_addr = inet_addr( addr );
sockServer = socket(AF_INET, SOCK_STREAM, 0);
if (sockServer == INVALID_SOCKET) {
printf("ERROR - Unable to create socket\n");
return TRUE;
}
// Enable Address Reuse
setsockopt(sockServer, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
// Enable No_Delay
setsockopt(sockServer, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
if ( bind(sockServer, (const sockaddr*)&local, sizeof(local)) == -1 ) {
printf("ERROR - Unable to bind to socket\n");
return TRUE;
}
if ( listen(sockServer,0) == -1) {
printf("ERROR - Unable to listen to socket\n");
return TRUE;
}
// Get client
printf("Server waiting for client\n");
len = sizeof(clientAddr);
while (sock == INVALID_SOCKET) {
sock = accept( sockServer,
(struct sockaddr *)&clientAddr,
(socklen_t *)&len );
}
printf("Accepted connection from %s, port %d\n",
inet_ntoa(clientAddr.sin_addr),
port) ;
// Enable Non-blocking I/O
flags = fcntl(sock, F_GETFL, 0);
if ( fcntl(sock, F_SETFL, flags | FNONBLOCK) == -1 ) {
printf("ERROR - Unable to set as nonblocking socket\n");
return TRUE;
}
}
return FALSE;
#endif
#ifdef WIN32
int stat;
int len;
int on=1;
unsigned long onl=1;
WSADATA wsaData;
struct sockaddr_in clientAddr;
if (sockServer == INVALID_SOCKET && sock == INVALID_SOCKET) {
if ( WSAStartup( 0x202, &wsaData ) == SOCKET_ERROR ) {
WSACleanup();
return TRUE;
}
sockServer = socket( AF_INET, SOCK_STREAM, 0 );
if ( sockServer < 0 ) {
printf("ERROR - Opening socket\n");
WSACleanup();
return TRUE;
}
local.sin_family = AF_INET;
local.sin_port = htons( port );
local.sin_addr.s_addr = INADDR_ANY;
to.sin_family = AF_INET;
to.sin_port = htons( port );
to.sin_addr.s_addr = inet_addr( addr );
// Enable Address Reuse (MUST be before the bind!)
stat = setsockopt( sockServer,
SOL_SOCKET,
SO_REUSEADDR,
(const char *)&on,
sizeof(on) );
if ( stat == SOCKET_ERROR ) {
printf("ERROR - Unable to enable address reuse\n");
closesocket( sockServer );
WSACleanup();
return TRUE;
}
stat = bind( sockServer,
(struct sockaddr *)&local,
sizeof(local) );
if ( stat == SOCKET_ERROR ) {
printf("ERROR - Bind to socket\n");
closesocket( sockServer );
WSACleanup();
return TRUE;
}
stat = listen( sockServer,
SOMAXCONN );
if ( stat == SOCKET_ERROR ) {
printf("ERROR - Listen to socket\n");
closesocket( sockServer );
WSACleanup();
return TRUE;
}
// Get Client
printf("Server waiting for client\n");
len = sizeof(clientAddr);
clientAddr.sin_port = 0;
while (sock == INVALID_SOCKET) {
sock = accept( sockServer,
(struct sockaddr *)&clientAddr,
&len );
}
printf("Accepted connection from %s, port %d\n",
inet_ntoa(clientAddr.sin_addr),
port) ;
// Enable Non-blocking I/O
stat = ioctlsocket( sock,
FIONBIO,
&onl );
if ( stat == SOCKET_ERROR ) {
printf("ERROR - Unable to enable Non-blocking I/O\n");
return TRUE;
}
}
return FALSE;
#endif
}
//--------------------------------------------------------------------------------
void tcpSocket::checkSocket(void)
{
#ifdef REDHAT
int len;
int flags;
int tempSock;
struct sockaddr_in clientAddr;
// Enable Non-blocking I/O
flags = fcntl(sockServer, F_GETFL, 0);
fcntl(sockServer, F_SETFL, flags | FNONBLOCK);
// Get Client
len = sizeof(clientAddr);
tempSock = accept( sockServer,
(struct sockaddr *)&clientAddr,
(socklen_t *)&len );
if (tempSock != INVALID_SOCKET) {
if (sock != INVALID_SOCKET) {
shutdown(sock, 2);
close(sock);
}
sock = tempSock;
}
#endif
#ifdef WIN32
int len;
unsigned long onl=1;
SOCKET tempSock;
struct sockaddr_in clientAddr;
// Enable Non-blocking I/O
ioctlsocket( sockServer, FIONBIO, &onl );
// Get Client
len = sizeof(clientAddr);
clientAddr.sin_port = 0;
tempSock = accept( sockServer,
(struct sockaddr *)&clientAddr,
&len );
if (tempSock != INVALID_SOCKET) {
if (sock != INVALID_SOCKET) {
shutdown( sock, SD_BOTH );
closesocket( sock );
}
sock = tempSock;
}
#endif
}
//--------------------------------------------------------------------------------
void tcpSocket::closeSocket(void)
{
#ifdef REDHAT
if (sockServer != INVALID_SOCKET) {
shutdown(sockServer, 2);
close(sockServer);
sockServer = INVALID_SOCKET;
}
if (sock != INVALID_SOCKET) {
shutdown(sock, 2);
close(sock);
sock = INVALID_SOCKET;
}
#endif
#ifdef WIN32
if (sockServer != INVALID_SOCKET) {
shutdown( sockServer, SD_BOTH );
closesocket( sockServer );
sockServer = INVALID_SOCKET;
}
if (sock != INVALID_SOCKET) {
shutdown( sock, SD_BOTH );
closesocket( sock );
sock = INVALID_SOCKET;
}
WSACleanup();
#endif
}
//--------------------------------------------------------------------------------
int tcpSocket::writeMsg(char *msg, int size)
{
int cnt;
if (sock != INVALID_SOCKET) {
cnt = sendto(sock, msg, size, 0, (struct sockaddr *)&to, sizeof(to));
if (cnt == size) return cnt;
else return -1;
}
return 0;
}
//--------------------------------------------------------------------------------
int tcpSocket::readMsg(char *msg, int maxSize)
{
int len;
int cnt;
struct sockaddr_in inSockAddr;
#ifdef REDHAT
if (sock != INVALID_SOCKET) {
len = sizeof(inSockAddr);
cnt = recvfrom(sock, msg, maxSize, 0, (struct sockaddr *)&inSockAddr, (socklen_t *)&len);
return cnt;
}
#else
if (sock != INVALID_SOCKET) {
len = sizeof(inSockAddr);
cnt = recvfrom(sock, msg, maxSize, 0, (struct sockaddr *)&inSockAddr, &len);
return cnt;
}
#endif
return 0;
}
//--------------------------------------------------------------------------------
int tcpSocket::peek(char *msg, int size)
{
int len;
int cnt;
struct sockaddr_in inSockAddr;
#ifdef REDHAT
if (sock != INVALID_SOCKET) {
len = sizeof(inSockAddr);
cnt = recvfrom(sock, msg, size, MSG_PEEK, (struct sockaddr *)&inSockAddr, (socklen_t *)&len);
return cnt;
}
#else
if (sock != INVALID_SOCKET) {
len = sizeof(inSockAddr);
cnt = recvfrom(sock, msg, size, MSG_PEEK, (struct sockaddr *)&inSockAddr, &len);
return cnt;
}
#endif
return 0;
}
//--------------------------------------------------------------------------------