00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "io/Socket.h"
00025
00026
00027 #include <errno.h>
00028 #ifndef _WIN32
00029 # include <netdb.h>
00030 #endif
00031
00032 namespace IXE {
00033 namespace io {
00034
00035 AbstractSocket::AbstractSocket(SOCKET sock, InetAddress inetAddress,
00036 in_port_t port) :
00037 sock(sock),
00038 inetAddress(inetAddress),
00039 port(port)
00040 { }
00041
00042 AbstractSocket::~AbstractSocket()
00043 {
00044 close();
00045 }
00046
00047 void AbstractSocket::close()
00048 {
00049 if (sock != INVALID_SOCKET) {
00050 closesocket(sock);
00051 sock = INVALID_SOCKET;
00052 }
00053 }
00054
00055 bool AbstractSocket::isOpen() const
00056 {
00057 return sock != INVALID_SOCKET;
00058 }
00059
00060 size_t AbstractSocket::read(char* buffer, size_t len)
00061 {
00062 int read = ::recv(sock, buffer, len, MSG_NOSIGNAL);
00063 if (read <= 0)
00064 close();
00065 return read;
00066 }
00067
00068 size_t AbstractSocket::readAll(char* buffer, size_t len)
00069 {
00070 char* start = buffer;
00071 int read;
00072 while (len > 0 && (read = ::recv(sock, buffer, len, MSG_NOSIGNAL)) != len) {
00073 if (read <= 0) {
00074 close();
00075 return buffer - start;
00076 }
00077 buffer += read;
00078 len -= read;
00079 }
00080 return buffer - start + len;
00081 }
00082
00083 size_t AbstractSocket::write(char const* buffer, size_t len)
00084 {
00085 int retval = ::send(sock, buffer, len, MSG_NOSIGNAL);
00086 if (retval <= 0)
00087 close();
00088 return retval;
00089 }
00090
00092
00093
00094
00095 Socket::Socket(SOCKET sock, InetAddress inetAddress, in_port_t port) :
00096 AbstractSocket(sock, inetAddress, port)
00097 { }
00098
00099 Socket::Socket(char const* host, int port)
00100 {
00101 connect(host, port);
00102 if (sock == INVALID_SOCKET)
00103 throw IOError("connect");
00104 }
00105
00106 bool Socket::connect(char const* host, int port)
00107 {
00108 if (host == 0 || host[0] == '\0')
00109 host = "localhost";
00110 struct hostent* hp = ::gethostbyname(host);
00111 if (hp == 0 || hp->h_addrtype != AF_INET)
00112 return false;
00113
00114 this->port = port;
00115 ::memcpy((char*)&inetAddress, hp->h_addr_list[0], sizeof(inetAddress));
00116
00117 return open();
00118 }
00119
00120 bool Socket::open()
00121 {
00122 struct sockaddr_in addr;
00123 addr.sin_port = htons(port);
00124 addr.sin_family = AF_INET;
00125 ::memcpy((char*)&addr.sin_addr, &inetAddress, sizeof(inetAddress));
00126
00127 sock = ::socket(PF_INET, SOCK_STREAM, 0);
00128 if (sock == INVALID_SOCKET)
00129 return false;
00130
00131 int retval;
00132 while ((retval = ::connect(sock, (struct sockaddr*)&addr, sizeof(addr)))
00133 == INVALID_SOCKET && (errno == EINTR))
00134 ;
00135 if (retval == SOCKET_ERROR) {
00136 closesocket(sock);
00137 return false;
00138 }
00139
00140 int const enabled = 1;
00141 # ifdef TCP_NODELAY
00142
00143
00144
00145
00146
00147
00148
00149 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (const char*)&enabled, sizeof(int));
00150 # endif
00151
00152 # ifdef SO_KEEPALIVE
00153 setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const char*)&enabled, sizeof(int));
00154 # endif
00155
00156 return true;
00157 }
00158
00159 #ifdef _WIN32
00160 class WinSockInitializer {
00161 public:
00162 WinSockInitializer() {
00163 int wVersionRequested = MAKEWORD(2, 0);
00164 WSADATA wsaData;
00165 WSAStartup(wVersionRequested, &wsaData);
00166 int sockopt = SO_SYNCHRONOUS_NONALERT;
00167 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&sockopt,
00168 sizeof(sockopt));
00169 }
00170 ~WinSockInitializer() {
00171 WSACleanup();
00172 }
00173
00174 } winSockInitializer;
00175 #endif
00176
00177 }
00178 }