// -------------------------------------------------- void WSAClientSocket::bind(Host &h) { struct sockaddr_in localAddr; #pragma warning(disable : 4244) if ((sockNum = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) #pragma warning(default : 4244) throw SockException("Can`t open socket"); setBlocking(false); setReuse(true); memset(&localAddr,0,sizeof(localAddr)); localAddr.sin_family = AF_INET; localAddr.sin_port = htons(h.port); localAddr.sin_addr.s_addr = INADDR_ANY; if( ::bind (sockNum, (sockaddr *)&localAddr, sizeof(localAddr)) == -1) throw SockException("Can`t bind socket"); if (::listen(sockNum,SOMAXCONN)) throw SockException("Can`t listen",WSAGetLastError()); host = h; }
// -------------------------------------------------- void UClientSocket::checkTimeout(bool r, bool w) { int err = errno; if ((err == EAGAIN) || (err == EINPROGRESS)) { //LOG("checktimeout %d %d",(int)r,(int)w); timeval timeout; fd_set read_fds; fd_set write_fds; timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO (&write_fds); if (w) { timeout.tv_sec = (int)this->writeTimeout/1000; FD_SET (sockNum, &write_fds); } FD_ZERO (&read_fds); if (r) { timeout.tv_sec = (int)this->readTimeout/1000; FD_SET (sockNum, &read_fds); } timeval *tp; if (timeout.tv_sec) tp = &timeout; else tp = NULL; int r=select (sockNum+1, &read_fds, &write_fds, NULL, tp); if (r == 0) throw TimeoutException(); else if (r == SOCKET_ERROR) throw SockException("select failed."); }else{ char str[256]; sprintf(str,"Closed: %s",strerror(err)); throw SockException(str); } }
Socket::Error Socket::error(Error err, const char *errs, long systemError) const { errid = err; errstr = errs; syserr = systemError; if(!err) return err; if(flags.thrown) return err; // prevents recursive throws flags.thrown = true; #ifdef CCXX_EXCEPTIONS switch(Thread::getException()) { case Thread::throwObject: THROW((Socket *)this); case Thread::throwException: if(!errs) errs = (char *)""; THROW(SockException(String(errs), err, systemError)); case Thread::throwNothing: break; } #endif return err; }
// -------------------------------------------------- void UClientSocket::open(Host &rh) { sockNum = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockNum == INVALID_SOCKET) throw SockException("Can`t open socket"); setBlocking(false); #ifdef DISABLE_NAGLE setNagle(false); #endif setBufSize(65535); host = rh; memset(&remoteAddr,0,sizeof(remoteAddr)); remoteAddr.sin_family = AF_INET; remoteAddr.sin_port = htons(host.port); remoteAddr.sin_addr.s_addr = htonl(host.ip); }
// -------------------------------------------------- void WSAClientSocket::setNagle(bool on) { int nodelay = (on==false); if (setsockopt(sockNum, SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof nodelay) == -1) throw SockException("Unable to set NODELAY"); }
// -------------------------------------------------- void WSAClientSocket::write(const void *p, int l) { while (l) { int r = send(sockNum, (char *)p, l, 0); if (r == SOCKET_ERROR) { checkTimeout(false,true); } else if (r == 0) { throw SockException("Closed on write"); } else if (r > 0) { stats.add(Stats::BYTESOUT,r); if (host.localIP()) stats.add(Stats::LOCALBYTESOUT,r); updateTotals(0,r); l -= r; p = (char *)p+r; } } }
// -------------------------------------------------- void UClientSocket::setReuse(bool yes) { unsigned long op = yes ? 1 : 0; if (setsockopt(sockNum,SOL_SOCKET,SO_REUSEADDR,(char *)&op,sizeof(op)) < 0) throw SockException("Unable to set REUSE"); }
// -------------------------------------------------- void WSAClientSocket::checkTimeout(bool r, bool w) { int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK) { timeval timeout; fd_set read_fds; fd_set write_fds; timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO (&write_fds); if (w) { timeout.tv_sec = (int)this->writeTimeout/1000; FD_SET (sockNum, &write_fds); } FD_ZERO (&read_fds); if (r) { timeout.tv_sec = (int)this->readTimeout/1000; FD_SET (sockNum, &read_fds); } timeval *tp; if (timeout.tv_sec) tp = &timeout; else tp = NULL; int r=select (NULL, &read_fds, &write_fds, NULL, tp); if (r == 0) throw TimeoutException(); else if (r == SOCKET_ERROR) throw SockException("select failed."); }else{ char str[32]; sprintf(str,"%d",err); throw SockException(str); } }
void CSocket::init() { WSADATA wsaData; WORD wVersionRequested = MAKEWORD( 2, 0 ); int err = ::WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { throw SockException("Unable to init sockets"); } }
// -------------------------------------------------- void WSAClientSocket::setLinger(int sec) { linger linger; linger.l_onoff = (sec>0)?1:0; linger.l_linger = sec; if (setsockopt(sockNum, SOL_SOCKET, SO_LINGER, (const char *)&linger, sizeof (linger)) == -1) throw SockException("Unable to set LINGER"); }
void CSocket::bind() { m_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_sock == INVALID_SOCKET) throw SockException("Can`t open socket"); _setBlocking(false); _setReuse(true); sockaddr_in localAddr = { 0 }; localAddr.sin_family = AF_INET; localAddr.sin_port = htons(DEFAULTPECA_PORT); localAddr.sin_addr.s_addr = INADDR_ANY; if( ::bind(m_sock, (sockaddr *)&localAddr, sizeof(localAddr)) == SOCKET_ERROR) throw SockException("Can`t bind socket"); if (::listen(m_sock, SOMAXCONN) == SOCKET_ERROR) throw SockException("Can`t listen",WSAGetLastError()); }
// -------------------------------------------------- /// 送信する void CSocket::send(const void *p, int nlength) { while (nlength) { int r = ::send(m_sock, (char *)p, nlength, 0); if (r == SOCKET_ERROR) { _checkTimeout(false); } else if (r == 0) { throw SockException("Closed on write"); } else if (r > 0) { nlength -= r; p = (char *)p + r; } } }
// -------------------------------------------------- void WSAClientSocket::init() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 0 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) throw SockException("Unable to init sockets"); //LOG4("WSAStartup: OK"); }
// -------------------------------------------------- void UClientSocket::bind(Host &h) { struct sockaddr_in localAddr; if ((sockNum = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) throw SockException("Can`t open socket"); setReuse(true); setBlocking(false); memset(&localAddr,0,sizeof(localAddr)); localAddr.sin_family = AF_INET; localAddr.sin_port = htons(h.port); localAddr.sin_addr.s_addr = INADDR_ANY; if( ::bind (sockNum, (sockaddr *)&localAddr, sizeof(localAddr)) == -1) throw SockException("Can`t bind socket"); if (::listen(sockNum,3)) throw SockException("Can`t listen"); host = h; }
// -------------------------------------------------- void CSocket::_checkTimeout(bool bRead) { int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK) { timeval timeout = { 0 }; fd_set read_fds; FD_ZERO (&read_fds); fd_set write_fds; FD_ZERO(&write_fds); if (bRead) { timeout.tv_sec = (int)m_uReadTimeout/1000; FD_SET(m_sock, &read_fds); } else { timeout.tv_sec = (int)m_uWriteTimeout/1000; FD_SET(m_sock, &write_fds); } timeval *tp; if (timeout.tv_sec) tp = &timeout; else tp = NULL; int r = select(NULL, &read_fds, &write_fds, NULL, tp); if (r == 0) throw TimeoutException(); else if (r == SOCKET_ERROR) throw SockException("select failed."); } else { char str[32]; sprintf(str, "%d", err); throw SockException(str); } }
// -------------------------------------------------- int UClientSocket::read(void *p, int l) { int bytesRead=0; while (l) { if (rbDataSize >= l) { memcpy(p, &apReadBuf[rbPos], l); rbPos += l; rbDataSize -= l; return l; } else if (rbDataSize > 0) { memcpy(p, &apReadBuf[rbPos], rbDataSize); p = (char *) p + rbDataSize; l -= rbDataSize; bytesRead += rbDataSize; } rbPos = 0; rbDataSize = 0; //int r = recv(sockNum, (char *)p, l, 0); int r = recv(sockNum, apReadBuf, RBSIZE, 0); if (r == SOCKET_ERROR) { // non-blocking sockets always fall through to here checkTimeout(true,false); }else if (r == 0) { throw SockException("Closed on read"); }else { stats.add(Stats::BYTESIN,r); if (host.localIP()) stats.add(Stats::LOCALBYTESIN,r); updateTotals(r,0); //bytesRead += r; //l -= r; //p = (char *)p+r; rbDataSize += r; } } return bytesRead; }
// -------------------------------------------------- void UClientSocket::checkTimeout2(bool r, bool w) { { //LOG("checktimeout %d %d",(int)r,(int)w); timeval timeout; fd_set read_fds; fd_set write_fds; timeout.tv_sec = 0; timeout.tv_usec = 0; FD_ZERO (&write_fds); if (w) { timeout.tv_sec = (int)this->writeTimeout/1000; FD_SET (sockNum, &write_fds); } FD_ZERO (&read_fds); if (r) { timeout.tv_sec = (int)this->readTimeout/1000; FD_SET (sockNum, &read_fds); } timeval *tp; if (timeout.tv_sec) tp = &timeout; else tp = NULL; int r=select (sockNum+1, &read_fds, &write_fds, NULL, tp); if (r == 0) throw TimeoutException(); else if (r == SOCKET_ERROR) throw SockException("select failed."); } }
// -------------------------------------------------- void WSAClientSocket::open(Host &rh) { #pragma warning(disable : 4244) sockNum = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); #pragma warning(default : 4244) if (sockNum == INVALID_SOCKET) throw SockException("Can`t open socket"); setBlocking(false); #ifdef DISABLE_NAGLE setNagle(false); #endif host = rh; memset(&remoteAddr,0,sizeof(remoteAddr)); remoteAddr.sin_family = AF_INET; remoteAddr.sin_port = htons(host.port); remoteAddr.sin_addr.S_un.S_addr = htonl(host.ip); }
// -------------------------------------------------- void UClientSocket::write(const void *p, int l) { while (l) { int r = send(sockNum, (char *)p, l, MSG_DONTWAIT|MSG_NOSIGNAL); if (r == SOCKET_ERROR) { // non-blocking sockets always fall through to here checkTimeout(false,true); }else if (r == 0) { throw SockException("Closed on write"); }else { stats.add(Stats::BYTESOUT,r); if (host.localIP()) stats.add(Stats::LOCALBYTESOUT,r); updateTotals(0,r); l -= r; p = (char *)p+r; } } }
// -------------------------------------------------- void CSocket::_setBlocking(bool yes) { unsigned long op = yes ? 0 : 1; if (ioctlsocket(m_sock, FIONBIO, &op) == SOCKET_ERROR) throw SockException("Can`t set blocking"); }
// -------------------------------------------------- void CSocket::_setReuse(bool yes) { unsigned long op = yes ? 1 : 0; if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&op, sizeof(op)) == SOCKET_ERROR) throw SockException("Unable to set REUSE"); }
// -------------------------------------------------- void WSAClientSocket::setBlocking(bool yes) { unsigned long op = yes ? 0 : 1; if (ioctlsocket(sockNum, FIONBIO, &op) == SOCKET_ERROR) throw SockException("Can`t set blocking"); }
// -------------------------------------------------- void UClientSocket::bufferingWrite(const void *p, int l) { if (bufList.isNull() && p != NULL){ while(l){ int r = send(sockNum, (char *)p, l, 0); if (r == SOCKET_ERROR){ int err = errno; if (err == EWOULDBLOCK){ bufList.add(p, l); // LOG_DEBUG("normal add"); break; } else { char str[32]; sprintf(str,"%d",err); throw SockException(str); } } else if (r == 0) { throw SockException("Closed on write"); } else if (r > 0){ stats.add(Stats::BYTESOUT,r); if (host.localIP()) stats.add(Stats::LOCALBYTESOUT,r); updateTotals(0,r); l -= r; p = (char *)p+r; } } } else { // LOG_DEBUG("***************BufferingWrite"); if (p) bufList.add(p,l); bool flg = true; while(flg){ SocketBuffer *tmp; tmp = bufList.getTop(); if (tmp){ // LOG_DEBUG("tmp->pos = %d, tmp->len = %d, %d", tmp->pos, tmp->len, tmp); while(tmp->pos < tmp->len){ int r = send(sockNum, (char*)(tmp->buf + tmp->pos), tmp->len - tmp->pos, 0); // LOG_DEBUG("send = %d", r); if (r == SOCKET_ERROR){ int err = errno; if (err == EWOULDBLOCK){ flg = false; break; } else { bufList.clear(); char str[32]; sprintf(str,"%d",err); throw SockException(str); } } else if (r == 0){ bufList.clear(); throw SockException("Closed on write"); } else if (r > 0){ stats.add(Stats::BYTESOUT,r); if (host.localIP()) stats.add(Stats::LOCALBYTESOUT,r); updateTotals(0,r); tmp->pos += r; if (tmp->pos >= tmp->len){ // LOG_DEBUG("deleteTop"); bufList.deleteTop(); break; } } } } else { flg = false; } } // LOG_DEBUG("bufferingWrite end"); } }
// -------------------------------------------------- void UClientSocket::setNagle(bool on) { int nodelay = (on==false); if (setsockopt(sockNum, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay,sizeof(nodelay)) < 0) throw SockException("Unable to set NODELAY"); }