You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

417 lines
10 KiB

#include "SocketObject.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <cerrno>
#include <iomanip>
using namespace std;
#if defined(__msdos__) || defined(WIN32)
SocketObject::SocketObject(void)
{
#ifdef __SOCKET_OBJECT_DEBUG
cout << "Windows SocketObject Konstruktor" << endl;
#endif
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD( 2, 0 );
_skSocket = INVALID_SOCKET;
WSAStartup(wVersionRequested, &wsaData);
}
SocketObject::SocketObject(SocketObject& sk)
{
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD( 2, 0 );
_skSocket = sk._skSocket;
sk._skSocket = INVALID_SOCKET;
WSAStartup(wVersionRequested, &wsaData);
}
SocketObject::~SocketObject(void)
{
Disconnect();
}
#endif
void SocketObject::setBlockingMode(bool nonblock)
{
int errorCode = 0;
#if defined(__msdos__) || defined(WIN32)
u_long iMode = 1;
if (!nonblock)
iMode=0;
if (0 != ioctlsocket(_skSocket, FIONBIO, &iMode))
{
errorCode = WSAGetLastError();
cout << "Set blocking mode ("<<iMode<<") failed! Errorcode "<< errorCode;
}
#else
//CHANGED: Use the boolean value
if (nonblock)
fcntl(_skSocket, F_SETFL, O_NONBLOCK);
#endif
}
int SocketObject::Bind(unsigned short int iPort)
{
#if defined(__msdos__) || defined(WIN32)
struct sockaddr_in saServerAddress;
// TCP-Socket erschaffen
_skSocket = socket(AF_INET, SOCK_STREAM, 0);
if (_skSocket == INVALID_SOCKET)
{
#ifdef __SOCKET_OBJECT_DEBUG
cout << "SocketObject::Bind(): INVALID SOCKET" << endl;
#endif
return 0;
}
// serverAdress wählen
memset(&saServerAddress, 0, sizeof(sockaddr_in));
saServerAddress.sin_family = AF_INET;
saServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
saServerAddress.sin_port = htons(iPort);
if ( bind(_skSocket, (sockaddr*)&saServerAddress, sizeof(sockaddr))== SOCKET_ERROR)
{
Disconnect();
return -1;
} else
{
#ifdef __SOCKET_OBJECT_DEBUG
cout << "SocketObject::Bind(): Alles ok" << endl;
#endif
return 0;
}
#else
struct sockaddr_in saServerAddress;
#ifdef __SOCKET_OBJECT_DEBUG
std::cout << "Port: " << iPort << endl;
#endif
// Socket erschaffen
_skSocket = socket(AF_INET, SOCK_STREAM, 0);
if (_skSocket < 0)
{
#ifdef __SOCKET_OBJECT_DEBUG
std::cout << "Fehler bei Bind - socket()" << std::endl;
#endif
return -1;
}
const int y = 1;
/* Socketoptionen fuer schnelles Verbinden setzen*/
setsockopt(_skSocket, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(int));
/* Initialisieren der aockaddr_in - structure */
// Server-Adresse mit 0 vorbelegen
memset(&saServerAddress, 0, sizeof(struct sockaddr_in));
// Domain
saServerAddress.sin_family = AF_INET;
// Addresse
saServerAddress.sin_addr.s_addr = INADDR_ANY;
// Port
saServerAddress.sin_port = htons( iPort );
// Versuch Socket an Port zu binden
if (0 > bind(_skSocket, (sockaddr*) &saServerAddress, sizeof(sockaddr)))
{
// Socket will nicht mehr lesen und schreiben
shutdown(_skSocket,2);
#ifdef __SOCKET_OBJECT_DEBUG
std::cout << "Fehler bei Bind!" << std::endl;
#endif
return -1;
} else
{
return 0;
}
#endif
}
int SocketObject::Listen( void )
{
// lauscht bei _skSocket, max Warteschlange = 2
return listen(_skSocket, 2);
// WIN32 : ,32
}
bool SocketObject::Accept(SocketObject &skAcceptSocket)
{
struct sockaddr_in saClientAddress;
int iClientSize = sizeof(sockaddr_in);
#if defined(__msdos__) || defined(WIN32)
skAcceptSocket._skSocket = accept(_skSocket, (struct sockaddr*)&saClientAddress, &iClientSize);
return !( skAcceptSocket._skSocket == INVALID_SOCKET);
#else
skAcceptSocket._skSocket = accept( _skSocket, (sockaddr*) &saClientAddress,(socklen_t*) &iClientSize);
return !( skAcceptSocket._skSocket == -1);
#endif
}
bool SocketObject::Connect(const char* szServerAddress, unsigned short int iPort, bool nonblock)
{
#if defined(__msdos__) || defined(WIN32)
struct sockaddr_in server_addr;
LPHOSTENT lpHost;
int error;
// Open the socket
_skSocket = socket(AF_INET, SOCK_STREAM, 0);
if (_skSocket == INVALID_SOCKET)
return false;
u_long iMode = 0;
if (nonblock)
iMode = 1;
ioctlsocket(_skSocket, FIONBIO, &iMode);
memset(&server_addr,0,sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(szServerAddress);
if (server_addr.sin_addr.s_addr == INADDR_NONE)
{
lpHost = gethostbyname(szServerAddress);
if (lpHost != NULL)
{
server_addr.sin_addr.s_addr = ((LPIN_ADDR)lpHost->h_addr)->s_addr;
}
else
return false;
}
server_addr.sin_port = htons(iPort);
error = connect(_skSocket, (struct sockaddr*)&server_addr, sizeof(sockaddr));
if (error == SOCKET_ERROR)
{
Disconnect();
return false;
}
return true;
#else
struct sockaddr_in server_addr;
int status;
// Socket erschaffen
_skSocket = socket(AF_INET, SOCK_STREAM, 0);
if (_skSocket < 0)
return false;
if (nonblock)
fcntl(_skSocket, F_SETFL, O_NONBLOCK);
// Initilisieren der sockaddr_in- Struktur
memset(&server_addr, 0, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
// server-Adresse bergeben
server_addr.sin_addr.s_addr = inet_addr(szServerAddress);
// std::cout << inet_ntoa (server_addr.sin_addr)<< std::endl;
// Port
server_addr.sin_port = htons(iPort);
// Verbindung herstellen
status = connect(_skSocket, (struct sockaddr*)&server_addr, sizeof(sockaddr));
if (status < 0)
{
shutdown(_skSocket,2);
return false;
}
return true;
#endif
}
bool SocketObject::Connect(const string szServerAddress, unsigned short int iPort, bool nonblock)
{
return Connect((char*) szServerAddress.c_str(), iPort, nonblock);
}
void SocketObject::Disconnect()
{
#if defined(__msdos__) || defined(WIN32)
if (_skSocket != INVALID_SOCKET)
{
closesocket(_skSocket);
_skSocket = INVALID_SOCKET;
}
#else
close(_skSocket);
#endif
}
int SocketObject::Recv(char *szBuffer, int iBufferLength, int iFlags)
{
return recv(_skSocket, szBuffer, iBufferLength, iFlags);
}
int SocketObject::Recv (string& s)
{
char buf [MAXRECV+1];
// cout << WSAGetLastError() << " in SocketObject::Recv, vor recv" << endl;
s = "";
memset(buf, 0, MAXRECV+1);
int status = Recv(buf, MAXRECV, 0);
switch (status)
{
case -1:
#ifdef __SOCKET_OBJECT_DEBUG
cout << "status: -1 errno: " << errno << " in SocketObject::Recv" << endl;
#endif
break;
case 0:
break;
default:
s = buf;
// strip the (expected) CRLF
if(s.length() == 1)
{
if(s[s.length()-1]=='\n' || s[s.length()-1]=='\r')
s.resize(s.length()-1);
} else if(s.length() >= 2)
{
if(s[s.length()-1]=='\n' && s[s.length()-2]=='\r')
s.resize(s.length()-2);
else if(s[s.length()-1]=='\n' || s[s.length()-1]=='\r')
s.resize(s.length()-1);
}
break;
}
return status;
}
int SocketObject::receiveLine(char* array, int arraySize)
{
//std::string ret;
char r;
int pos = 0;
while (pos<arraySize-2)
{
switch(recv(_skSocket, &r, 1, 0))
{
case 0: // not connected anymore;
return 0;
case -1:
return -1;
}
// check for carriage return or line feed (MAC: CR, Linux: LF, Windows: CRLF)
if ((r == char(13)) || (r == char(10)))
{
if (pos > 0)
{
array[pos]='\0';
return pos;
}
}else
{
array[pos] = r;
pos++;
}
}
return pos;
}
std::string SocketObject::receiveLine()
{
std::string ret;
char r;
while (1)
{
//This will not work under windows if the blocking mode is non-blocking
// -1 will indicate that there is no value, it is not an error !!!
//http://msdn.microsoft.com/en-us/library/ms740121(VS.85).aspx
//For linux see:
//http://linux.about.com/library/cmd/blcmdl2_recv.htm
//If no messages are available at the socket, the receive calls wait for a message to arrive,
//unless the socket is nonblocking (see fcntl(2)) in which case the value -1 is returned and
// the external variable errno set to EAGAIN.
switch(recv(_skSocket, &r, 1, 0))
{
case 0: // not connected anymore;
return SOCKETOBJECT_NOT_CONNECTED;
case -1: // error
return SOCKETOBJECT_RECV_ERROR;
}
// check for carriage return or line feed (MAC: CR, Linux: LF, Windows: CRLF)
if ((r == char(13)) || (r == char(10)))
{
if (ret.length() > 0)
return ret;
} else
{
ret += r;
}
}
}
int SocketObject::Send(const char *szBuffer, int iBufferLength, int iFlags)
{
return send(_skSocket,szBuffer,iBufferLength, iFlags);
}
int SocketObject::Send (const string s)
{
string str = s;
// add the (expected) CRLF
if(str == "")
{
str = "\n\r";
} else if(str.size() == 1)
{
if(str[0] == '\r')
{
str = "\n\r";
} else if(str[0] != '\n')
{
str += "\n\r";
}
} else if(str.size() >= 2)
{
if(str[str.length()-1] != '\n' || str[str.length()-2]!='\r')
{
str += "\n\r";
}
}
#if defined(__msdos__) || defined(WIN32)
return Send((char*) str.c_str(), (int) str.size(), 0);
#else
return Send((char*) str.c_str(), (int) str.size(), (int) MSG_NOSIGNAL);
#endif
}