00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "../include/IPSA/network/TCPSocket.h"
00027 #include <cstdio>
00028
00029 #ifdef WIN32
00030 #else
00031 #include <netdb.h>
00032 #include <errno.h>
00033 #include <sys/ioctl.h>
00034 #include <arpa/inet.h>
00035 #endif
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 CTCPSocket::CTCPSocket(const std::string& address, int nPort, bool isServer, int nTimeoutMilliSec)
00046 :PORT(nPort),
00047 remoteAddress(address),
00048 timeout(nTimeoutMilliSec),
00049 LISTEN_BACKLOG(5),
00050 bInitialised(false),
00051 IS_SERVER_SOCKET(isServer),
00052 tcp_socket(-1),
00053 server_listen_socket(-1)
00054 {
00055 #ifdef WIN32
00056 WSADATA wsadata;
00057 if (WSAStartup(MAKEWORD(1, 1), &wsadata) != 0)
00058 {
00059 printf("WSAStartup() failed, %lu\n", (unsigned long)GetLastError());
00060 exit(1);
00061 }
00062 #endif
00063
00064 this->address.sin_family = AF_INET;
00065 this->address.sin_port = htons(PORT);
00066 }
00067
00068
00069 CTCPSocket::~CTCPSocket()
00070 {
00071 closeSocket();
00072
00073 #ifdef WIN32
00074 WSACleanup();
00075 #endif
00076 }
00077
00078
00079 bool CTCPSocket::openSocket()
00080 {
00081 bInitialised = false;
00082
00083
00084 tcp_socket = socket(PF_INET, SOCK_STREAM, 0);
00085
00086 bool result = tcp_socket != INVALID_SOCKET;
00087
00088 if (!result)
00089 {
00090 printf("error: could not create socket\n");
00091 perror("CTCPSocket::openSocket() -> socket()");
00092 return false;
00093 }
00094
00095 #ifndef WIN32
00096
00097 int yes = 1;
00098 if (-1 == setsockopt(tcp_socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)))
00099 perror("setsockopt()");
00100 #endif // !WIN32
00101
00102 if (IS_SERVER_SOCKET)
00103 {
00104 server_listen_socket = tcp_socket;
00105 address.sin_addr.s_addr = htonl(INADDR_ANY);
00106 memset(address.sin_zero, '\0', sizeof address.sin_zero);
00107
00108 if (bind(tcp_socket, (struct sockaddr *) &address, sizeof(address)) == -1)
00109 {
00110 printf("error: could not bind to address and port '%s:%i'\n", remoteAddress.c_str(), PORT);
00111 perror("CTCPSocket::openSocket() -> bind()");
00112 closeSocket();
00113 return false;
00114 }
00115 if (-1 == listen(tcp_socket, LISTEN_BACKLOG))
00116 perror("listen");
00117
00118 printf("Waiting for connection ... ");
00119 #ifdef WIN32
00120 int sin_size = sizeof(struct sockaddr_in);
00121 #else
00122 socklen_t sin_size = sizeof(struct sockaddr_in);
00123 #endif // !WIN32
00124 sockaddr_in remote_host;
00125 tcp_socket = accept(server_listen_socket, (struct sockaddr*) &remote_host, &sin_size);
00126 if (-1 == tcp_socket)
00127 {
00128 printf("error\n");
00129 perror("accept()");
00130 return false;
00131 }
00132 #ifdef WIN32
00133 printf("accepted\n");
00134 #else
00135 char ip_string[INET_ADDRSTRLEN];
00136 inet_ntop(remote_host.sin_family, &remote_host.sin_addr.s_addr, ip_string, INET_ADDRSTRLEN);
00137 printf("accepted\nConnected from %s:%d\n", ip_string, remote_host.sin_port);
00138 #endif
00139 }
00140 else
00141 {
00142 struct hostent* host = gethostbyname(remoteAddress.c_str());
00143 if (NULL == host)
00144 {
00145 #ifdef WIN32
00146 printf("gethostbyname(%s) failed with error: %ld\n",remoteAddress.c_str(),WSAGetLastError());
00147 #else
00148 herror("CTCPSocket::openSocket() -> gethostbyname()");
00149 #endif
00150 return false;
00151 }
00152 address.sin_addr = *((struct in_addr*) host->h_addr);
00153 memset(address.sin_zero, '\0', sizeof address.sin_zero);
00154
00155 if (-1 == connect(tcp_socket, (struct sockaddr *)&address, sizeof address)) {
00156 perror("CTCPSocket::openSocket() -> connect()");
00157 return false;
00158 }
00159 }
00160
00161 if (!setNonBlocking(timeout))
00162 {
00163 printf("error: could not set socket to non blocking for receiving\n");
00164 closeSocket();
00165 return false;
00166 }
00167
00168 bInitialised = true;
00169
00170 return true;
00171 }
00172
00173
00174 void CTCPSocket::closeSocket()
00175 {
00176 #ifdef WIN32
00177 closesocket(tcp_socket);
00178 #else
00179 close(tcp_socket);
00180 #endif
00181
00182 if (IS_SERVER_SOCKET)
00183 {
00184 #ifdef WIN32
00185 closesocket(server_listen_socket);
00186 #else
00187 close(server_listen_socket);
00188 #endif
00189 }
00190
00191 bInitialised = false;
00192 }
00193
00194
00195 bool CTCPSocket::setNonBlocking(int nTimeoutMilliSec)
00196 {
00197 if (0 == nTimeoutMilliSec)
00198 {
00199 unsigned long mode = 1;
00200
00201 #ifdef WIN32
00202 const int RESULT = ioctlsocket(tcp_socket, FIONBIO, &mode);
00203 #else
00204 const int RESULT = ioctl(tcp_socket, FIONBIO, &mode);
00205 #endif
00206
00207 if (RESULT != 0)
00208 return false;
00209 }
00210 else if (0 > nTimeoutMilliSec)
00211 {
00212
00213 unsigned long disableFlag = 0;
00214 #ifdef WIN32
00215 const int RESULT = ioctlsocket(tcp_socket, FIONBIO, &disableFlag);
00216 #else
00217 const int RESULT = ioctl(tcp_socket, FIONBIO, &disableFlag);
00218 #endif // !WIN32
00219 if (-1 == RESULT)
00220 perror("CTCPSocket::setNonBlocking() -> ioctl(tcp_socket, FIONBIO)");
00221 }
00222 else
00223 {
00224 #ifdef WIN32
00225 __int64 to;
00226 to = (__int64) nTimeoutMilliSec;
00227 const int RESULT = setsockopt(tcp_socket, SOL_SOCKET, SO_RCVTIMEO, (char FAR*) &to, sizeof(__int64));
00228 #else
00229 struct timeval to;
00230 to.tv_sec = (nTimeoutMilliSec / 1000);
00231 to.tv_usec = (nTimeoutMilliSec % 1000) * 1000;
00232 const int RESULT = setsockopt(tcp_socket, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(struct timeval));
00233 #endif
00234
00235 if (RESULT < 0)
00236 return false;
00237 }
00238
00239 return true;
00240 }
00241
00242
00243 bool CTCPSocket::isConnected()
00244 {
00245 return bInitialised;
00246 }
00247
00248
00249 int CTCPSocket::send(const char *pData, int nSize) const
00250 {
00251 if (!bInitialised)
00252 {
00253 printf("error: could not send: socket not initialised\n");
00254 return -1;
00255 }
00256
00257 int sentBytes = ::send(tcp_socket, pData, nSize, 0);
00258
00259
00260
00261 return sentBytes;
00262 }
00263
00264
00265 int CTCPSocket::send(const std::string& data) const
00266 {
00267 return this->send(data.c_str(), data.size());
00268 }
00269
00270
00271 int CTCPSocket::receive(char *pBuffer, int nSize)
00272 {
00273 if (!bInitialised)
00274 {
00275 printf("error: could not receive: socket not initialised\n");
00276 return -1;
00277 }
00278
00279 int receivedBytes = recv(tcp_socket, pBuffer, nSize, 0);
00280
00281
00282 if (0 == receivedBytes)
00283 bInitialised = false;
00284 return receivedBytes;
00285 }