This commit is contained in:
workinghard
2015-06-29 12:10:00 -07:00
parent aa41f7bf40
commit 2642157516
4 changed files with 305 additions and 0 deletions

119
Cube4Fun/tcpconnector.cpp Executable file
View File

@@ -0,0 +1,119 @@
/*
TCPConnector.h
TCPConnector class definition. TCPConnector provides methods to actively
establish TCP/IP connections with a server.
------------------------------------------
Copyright <20> 2013 [Vic Hargrave - http://vichargrave.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
*/
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>
#include "tcpconnector.h"
TCPStream* TCPConnector::connect(const char* server, int port)
{
struct sockaddr_in address;
memset (&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
if (resolveHostName(server, &(address.sin_addr)) != 0 ) {
inet_pton(PF_INET, server, &(address.sin_addr));
}
int sd = socket(AF_INET, SOCK_STREAM, 0);
if (::connect(sd, (struct sockaddr*)&address, sizeof(address)) != 0) {
perror("connect() failed");
return NULL;
}
return new TCPStream(sd, &address);
}
TCPStream* TCPConnector::connect(const char* server, int port, int timeout)
{
if (timeout == 0) return connect(server, port);
struct sockaddr_in address;
memset (&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
if (resolveHostName(server, &(address.sin_addr)) != 0 ) {
inet_pton(PF_INET, server, &(address.sin_addr));
}
long arg;
fd_set sdset;
struct timeval tv;
socklen_t len;
int result = -1, valopt, sd = socket(AF_INET, SOCK_STREAM, 0);
// Set socket to non-blocking
arg = fcntl(sd, F_GETFL, NULL);
arg |= O_NONBLOCK;
fcntl(sd, F_SETFL, arg);
// Connect with time limit
string message;
if ((result = ::connect(sd, (struct sockaddr *)&address, sizeof(address))) < 0)
{
if (errno == EINPROGRESS)
{
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&sdset);
FD_SET(sd, &sdset);
if (select(sd+1, NULL, &sdset, NULL, &tv) > 0)
{
len = sizeof(int);
getsockopt(sd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &len);
if (valopt) {
fprintf(stderr, "connect() error %d - %s\n", valopt, strerror(valopt));
}
// connection established
else result = 0;
}
else fprintf(stderr, "connect() timed out\n");
}
else fprintf(stderr, "connect() error %d - %s\n", errno, strerror(errno));
}
// Return socket to blocking mode
arg = fcntl(sd, F_GETFL, NULL);
arg &= (~O_NONBLOCK);
fcntl(sd, F_SETFL, arg);
// Create stream object if connected
if (result == -1) return NULL;
return new TCPStream(sd, &address);
}
int TCPConnector::resolveHostName(const char* hostname, struct in_addr* addr)
{
struct addrinfo *res;
int result = getaddrinfo (hostname, NULL, NULL, &res);
if (result == 0) {
memcpy(addr, &((struct sockaddr_in *) res->ai_addr)->sin_addr, sizeof(struct in_addr));
freeaddrinfo(res);
}
return result;
}

40
Cube4Fun/tcpconnector.h Executable file
View File

@@ -0,0 +1,40 @@
/*
TCPConnector.h
TCPConnector class interface. TCPConnector provides methods to actively
establish TCP/IP connections with a server.
------------------------------------------
Copyright <20> 2013 [Vic Hargrave - http://vichargrave.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License
*/
#ifndef __tcpconnector_h__
#define __tcpconnector_h__
#include <netinet/in.h>
#include "tcpstream.h"
class TCPConnector
{
public:
TCPStream* connect(const char* server, int port);
TCPStream* connect(const char* server, int port, int timeout);
private:
int resolveHostName(const char* host, struct in_addr* addr);
};
#endif

80
Cube4Fun/tcpstream.cpp Executable file
View File

@@ -0,0 +1,80 @@
/*
TCPStream.h
TCPStream class definition. TCPStream provides methods to trasnfer
data between peers over a TCP/IP connection.
------------------------------------------
Copyright <20> 2013 [Vic Hargrave - http://vichargrave.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include <arpa/inet.h>
#include "tcpstream.h"
TCPStream::TCPStream(int sd, struct sockaddr_in* address) : m_sd(sd) {
char ip[50];
inet_ntop(PF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, sizeof(ip)-1);
m_peerIP = ip;
m_peerPort = ntohs(address->sin_port);
}
TCPStream::~TCPStream()
{
close(m_sd);
}
ssize_t TCPStream::send(const char* buffer, size_t len)
{
return write(m_sd, buffer, len);
}
ssize_t TCPStream::receive(char* buffer, size_t len, int timeout)
{
if (timeout <= 0) return read(m_sd, buffer, len);
if (waitForReadEvent(timeout) == true)
{
return read(m_sd, buffer, len);
}
return connectionTimedOut;
}
string TCPStream::getPeerIP()
{
return m_peerIP;
}
int TCPStream::getPeerPort()
{
return m_peerPort;
}
bool TCPStream::waitForReadEvent(int timeout)
{
fd_set sdset;
struct timeval tv;
tv.tv_sec = timeout;
tv.tv_usec = 0;
FD_ZERO(&sdset);
FD_SET(m_sd, &sdset);
if (select(m_sd+1, &sdset, NULL, NULL, &tv) > 0)
{
return true;
}
return false;
}

66
Cube4Fun/tcpstream.h Executable file
View File

@@ -0,0 +1,66 @@
/*
TCPStream.h
TCPStream class interface. TCPStream provides methods to trasnfer
data between peers over a TCP/IP connection.
------------------------------------------
Copyright <20> 2013 [Vic Hargrave - http://vichargrave.com]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __tcpstream_h__
#define __tcpstream_h__
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string>
using namespace std;
class TCPStream
{
int m_sd;
string m_peerIP;
int m_peerPort;
public:
friend class TCPAcceptor;
friend class TCPConnector;
~TCPStream();
ssize_t send(const char* buffer, size_t len);
ssize_t receive(char* buffer, size_t len, int timeout=0);
string getPeerIP();
int getPeerPort();
enum {
connectionClosed = 0,
connectionReset = -1,
connectionTimedOut = -2
};
private:
bool waitForReadEvent(int timeout);
TCPStream(int sd, struct sockaddr_in* address);
TCPStream();
TCPStream(const TCPStream& stream);
};
#endif