00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "PracticalSocket.h"
00021
00022 #ifdef WIN32
00023 #include <winsock.h>
00024 typedef int socklen_t;
00025 typedef char raw_type;
00026 #else
00027 #include <sys/types.h>
00028 #include <sys/socket.h>
00029 #include <netdb.h>
00030 #include <arpa/inet.h>
00031 #include <unistd.h>
00032 #include <netinet/in.h>
00033 typedef void raw_type;
00034 #endif
00035
00036 #include <errno.h>
00037
00038 using namespace std;
00039
00040 #ifdef WIN32
00041 static bool initialized = false;
00042 #endif
00043
00044
00045
00046 SocketException::SocketException(const string &message, bool inclSysMsg)
00047 throw() : userMessage(message) {
00048 if (inclSysMsg) {
00049 userMessage.append(": ");
00050 userMessage.append(strerror(errno));
00051 }
00052 }
00053
00054 SocketException::~SocketException() throw() {
00055 }
00056
00057 const char *SocketException::what() const throw() {
00058 return userMessage.c_str();
00059 }
00060
00061
00062 static void fillAddr(const string &address, unsigned short port,
00063 sockaddr_in &addr) {
00064 memset(&addr, 0, sizeof(addr));
00065 addr.sin_family = AF_INET;
00066
00067 hostent *host;
00068 if ((host = gethostbyname(address.c_str())) == NULL) {
00069
00070
00071 throw SocketException("Failed to resolve name (gethostbyname())");
00072 }
00073 addr.sin_addr.s_addr = *((unsigned long *) host->h_addr_list[0]);
00074
00075 addr.sin_port = htons(port);
00076 }
00077
00078
00079
00080 Socket::Socket(int type, int protocol) throw(SocketException) {
00081 #ifdef WIN32
00082 if (!initialized) {
00083 WORD wVersionRequested;
00084 WSADATA wsaData;
00085
00086 wVersionRequested = MAKEWORD(2, 0);
00087 if (WSAStartup(wVersionRequested, &wsaData) != 0) {
00088 throw SocketException("Unable to load WinSock DLL");
00089 }
00090 initialized = true;
00091 }
00092 #endif
00093
00094
00095 if ((sockDesc = socket(PF_INET, type, protocol)) < 0) {
00096 throw SocketException("Socket creation failed (socket())", true);
00097 }
00098 }
00099
00100 Socket::Socket(int sockDesc) {
00101 this->sockDesc = sockDesc;
00102 }
00103
00104 Socket::~Socket() {
00105 #ifdef WIN32
00106 ::closesocket(sockDesc);
00107 #else
00108 ::close(sockDesc);
00109 #endif
00110 sockDesc = -1;
00111 }
00112
00113 string Socket::getLocalAddress() throw(SocketException) {
00114 sockaddr_in addr;
00115 unsigned int addr_len = sizeof(addr);
00116
00117 if (getsockname(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) {
00118 throw SocketException("Fetch of local address failed (getsockname())", true);
00119 }
00120 return inet_ntoa(addr.sin_addr);
00121 }
00122
00123 unsigned short Socket::getLocalPort() throw(SocketException) {
00124 sockaddr_in addr;
00125 unsigned int addr_len = sizeof(addr);
00126
00127 if (getsockname(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) {
00128 throw SocketException("Fetch of local port failed (getsockname())", true);
00129 }
00130 return ntohs(addr.sin_port);
00131 }
00132
00133 void Socket::setLocalPort(unsigned short localPort) throw(SocketException) {
00134
00135 sockaddr_in localAddr;
00136 memset(&localAddr, 0, sizeof(localAddr));
00137 localAddr.sin_family = AF_INET;
00138 localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00139 localAddr.sin_port = htons(localPort);
00140
00141 if (bind(sockDesc, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) {
00142 throw SocketException("Set of local port failed (bind())", true);
00143 }
00144 }
00145
00146 void Socket::setLocalAddressAndPort(const string &localAddress,
00147 unsigned short localPort) throw(SocketException) {
00148
00149 sockaddr_in localAddr;
00150 fillAddr(localAddress, localPort, localAddr);
00151
00152 if (bind(sockDesc, (sockaddr *) &localAddr, sizeof(sockaddr_in)) < 0) {
00153 throw SocketException("Set of local address and port failed (bind())", true);
00154 }
00155 }
00156
00157 void Socket::cleanUp() throw(SocketException) {
00158 #ifdef WIN32
00159 if (WSACleanup() != 0) {
00160 throw SocketException("WSACleanup() failed");
00161 }
00162 #endif
00163 }
00164
00165 unsigned short Socket::resolveService(const string &service,
00166 const string &protocol) {
00167 struct servent *serv;
00168
00169 if ((serv = getservbyname(service.c_str(), protocol.c_str())) == NULL)
00170 return atoi(service.c_str());
00171 else
00172 return ntohs(serv->s_port);
00173 }
00174
00175
00176
00177 CommunicatingSocket::CommunicatingSocket(int type, int protocol)
00178 throw(SocketException) : Socket(type, protocol) {
00179 }
00180
00181 CommunicatingSocket::CommunicatingSocket(int newConnSD) : Socket(newConnSD) {
00182 }
00183
00184 void CommunicatingSocket::connect(const string &foreignAddress,
00185 unsigned short foreignPort) throw(SocketException) {
00186
00187 sockaddr_in destAddr;
00188 fillAddr(foreignAddress, foreignPort, destAddr);
00189
00190
00191 if (::connect(sockDesc, (sockaddr *) &destAddr, sizeof(destAddr)) < 0) {
00192 throw SocketException("Connect failed (connect())", true);
00193 }
00194 }
00195
00196 void CommunicatingSocket::send(const void *buffer, int bufferLen)
00197 throw(SocketException) {
00198 #ifdef WIN32
00199 if (::send(sockDesc, (raw_type *) buffer, bufferLen, 0) < 0) {
00200 #else
00201 if (::send(sockDesc, (raw_type *) buffer, bufferLen, MSG_NOSIGNAL) < 0) {
00202 #endif
00203 throw SocketException("Send failed (send())", true);
00204 }
00205 }
00206
00207 int CommunicatingSocket::recv(void *buffer, int bufferLen)
00208 throw(SocketException) {
00209 int rtn;
00210 if ((rtn = ::recv(sockDesc, (raw_type *) buffer, bufferLen, 0)) < 0) {
00211 throw SocketException("Received failed (recv())", true);
00212 }
00213
00214 return rtn;
00215 }
00216
00217 string CommunicatingSocket::getForeignAddress()
00218 throw(SocketException) {
00219 sockaddr_in addr;
00220 unsigned int addr_len = sizeof(addr);
00221
00222 if (getpeername(sockDesc, (sockaddr *) &addr,(socklen_t *) &addr_len) < 0) {
00223 throw SocketException("Fetch of foreign address failed (getpeername())", true);
00224 }
00225 return inet_ntoa(addr.sin_addr);
00226 }
00227
00228 unsigned short CommunicatingSocket::getForeignPort() throw(SocketException) {
00229 sockaddr_in addr;
00230 unsigned int addr_len = sizeof(addr);
00231
00232 if (getpeername(sockDesc, (sockaddr *) &addr, (socklen_t *) &addr_len) < 0) {
00233 throw SocketException("Fetch of foreign port failed (getpeername())", true);
00234 }
00235 return ntohs(addr.sin_port);
00236 }
00237
00238
00239
00240 TCPSocket::TCPSocket()
00241 throw(SocketException) : CommunicatingSocket(SOCK_STREAM,
00242 IPPROTO_TCP) {
00243 }
00244
00245 TCPSocket::TCPSocket(const string &foreignAddress, unsigned short foreignPort)
00246 throw(SocketException) : CommunicatingSocket(SOCK_STREAM, IPPROTO_TCP) {
00247 connect(foreignAddress, foreignPort);
00248 }
00249
00250 TCPSocket::TCPSocket(int newConnSD) : CommunicatingSocket(newConnSD) {
00251 }
00252
00253
00254
00255 TCPServerSocket::TCPServerSocket(unsigned short localPort, int queueLen)
00256 throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) {
00257 setLocalPort(localPort);
00258 setListen(queueLen);
00259 }
00260
00261 TCPServerSocket::TCPServerSocket(const string &localAddress,
00262 unsigned short localPort, int queueLen)
00263 throw(SocketException) : Socket(SOCK_STREAM, IPPROTO_TCP) {
00264 setLocalAddressAndPort(localAddress, localPort);
00265 setListen(queueLen);
00266 }
00267
00268 TCPSocket *TCPServerSocket::accept() throw(SocketException) {
00269 int newConnSD;
00270 if ((newConnSD = ::accept(sockDesc, NULL, 0)) < 0) {
00271 throw SocketException("Accept failed (accept())", true);
00272 }
00273
00274 return new TCPSocket(newConnSD);
00275 }
00276
00277 void TCPServerSocket::setListen(int queueLen) throw(SocketException) {
00278 if (listen(sockDesc, queueLen) < 0) {
00279 throw SocketException("Set listening socket failed (listen())", true);
00280 }
00281 }
00282
00283
00284
00285 UDPSocket::UDPSocket() throw(SocketException) : CommunicatingSocket(SOCK_DGRAM,
00286 IPPROTO_UDP) {
00287 setBroadcast();
00288 }
00289
00290 UDPSocket::UDPSocket(unsigned short localPort) throw(SocketException) :
00291 CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) {
00292 setLocalPort(localPort);
00293 setBroadcast();
00294 }
00295
00296 UDPSocket::UDPSocket(const string &localAddress, unsigned short localPort)
00297 throw(SocketException) : CommunicatingSocket(SOCK_DGRAM, IPPROTO_UDP) {
00298 setLocalAddressAndPort(localAddress, localPort);
00299 setBroadcast();
00300 }
00301
00302 void UDPSocket::setBroadcast() {
00303
00304
00305 int broadcastPermission = 1;
00306 setsockopt(sockDesc, SOL_SOCKET, SO_BROADCAST,
00307 (raw_type *) &broadcastPermission, sizeof(broadcastPermission));
00308 }
00309
00310 void UDPSocket::disconnect() throw(SocketException) {
00311 sockaddr_in nullAddr;
00312 memset(&nullAddr, 0, sizeof(nullAddr));
00313 nullAddr.sin_family = AF_UNSPEC;
00314
00315
00316 if (::connect(sockDesc, (sockaddr *) &nullAddr, sizeof(nullAddr)) < 0) {
00317 #ifdef WIN32
00318 if (errno != WSAEAFNOSUPPORT) {
00319 #else
00320 if (errno != EAFNOSUPPORT) {
00321 #endif
00322 throw SocketException("Disconnect failed (connect())", true);
00323 }
00324 }
00325 }
00326
00327 void UDPSocket::sendTo(const void *buffer, int bufferLen,
00328 const string &foreignAddress, unsigned short foreignPort)
00329 throw(SocketException) {
00330 sockaddr_in destAddr;
00331 fillAddr(foreignAddress, foreignPort, destAddr);
00332
00333
00334 if (sendto(sockDesc, (raw_type *) buffer, bufferLen, 0,
00335 (sockaddr *) &destAddr, sizeof(destAddr)) != bufferLen) {
00336 throw SocketException("Send failed (sendto())", true);
00337 }
00338 }
00339
00340 int UDPSocket::recvFrom(void *buffer, int bufferLen, string &sourceAddress,
00341 unsigned short &sourcePort) throw(SocketException) {
00342 sockaddr_in clntAddr;
00343 socklen_t addrLen = sizeof(clntAddr);
00344 int rtn;
00345 if ((rtn = recvfrom(sockDesc, (raw_type *) buffer, bufferLen, 0,
00346 (sockaddr *) &clntAddr, (socklen_t *) &addrLen)) < 0) {
00347 throw SocketException("Receive failed (recvfrom())", true);
00348 }
00349 sourceAddress = inet_ntoa(clntAddr.sin_addr);
00350 sourcePort = ntohs(clntAddr.sin_port);
00351
00352 return rtn;
00353 }
00354
00355 #ifndef WIN32
00356
00357 void UDPSocket::setMulticastTTL(unsigned char multicastTTL) throw(SocketException) {
00358 if (setsockopt(sockDesc, IPPROTO_IP, IP_MULTICAST_TTL,
00359 (raw_type *) &multicastTTL, sizeof(multicastTTL)) < 0) {
00360 throw SocketException("Multicast TTL set failed (setsockopt())", true);
00361 }
00362 }
00363
00364 void UDPSocket::joinGroup(const string &multicastGroup) throw(SocketException) {
00365 struct ip_mreq multicastRequest;
00366
00367 multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str());
00368 multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
00369 if (setsockopt(sockDesc, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00370 (raw_type *) &multicastRequest,
00371 sizeof(multicastRequest)) < 0) {
00372 throw SocketException("Multicast group join failed (setsockopt())", true);
00373 }
00374 }
00375
00376 void UDPSocket::leaveGroup(const string &multicastGroup) throw(SocketException) {
00377 struct ip_mreq multicastRequest;
00378
00379 multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastGroup.c_str());
00380 multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY);
00381 if (setsockopt(sockDesc, IPPROTO_IP, IP_DROP_MEMBERSHIP,
00382 (raw_type *) &multicastRequest,
00383 sizeof(multicastRequest)) < 0) {
00384 throw SocketException("Multicast group leave failed (setsockopt())", true);
00385 }
00386 }
00387 #endif