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
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
|
|
}
|
|
|