📄 socket.cpp
字号:
}Socket::Error Socket::setKeepAlive(bool enable){ int opt = (enable ? ~0: 0);#if (defined(SO_KEEPALIVE) || defined(WIN32)) if(setsockopt(so, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, (socklen_t)sizeof(opt))) return error(errKeepaliveDenied,"Could not set socket keep-alive option",socket_errno);#endif flags.keepalive = enable; return errSuccess;}Socket::Error Socket::setLinger(bool linger){#ifdef SO_LINGER flags.linger = linger; return errSuccess;#else return error(errServiceUnavailable,"Socket lingering not supported");#endif}Socket::Error Socket::setRouting(bool enable){ int opt = (enable ? 1 : 0);#ifdef SO_DONTROUTE if(setsockopt(so, SOL_SOCKET, SO_DONTROUTE, (char *)&opt, (socklen_t)sizeof(opt))) return error(errRoutingDenied,"Could not set dont-route socket option",socket_errno);#endif flags.route = enable; return errSuccess;}Socket::Error Socket::setNoDelay(bool enable){ int opt = (enable ? 1 : 0); if(setsockopt(so, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, (socklen_t)sizeof(opt))) return error(errNoDelay,"Could not set tcp-nodelay socket option",socket_errno); return errSuccess;}Socket::Error Socket::setTypeOfService(Tos service){#ifdef SOL_IP unsigned char tos; switch(service) {#ifdef IPTOS_LOWDELAY case tosLowDelay: tos = IPTOS_LOWDELAY; break;#endif#ifdef IPTOS_THROUGHPUT case tosThroughput: tos = IPTOS_THROUGHPUT; break;#endif#ifdef IPTOS_RELIABILITY case tosReliability: tos = IPTOS_RELIABILITY; break;#endif#ifdef IPTOS_MINCOST case tosMinCost: tos = IPTOS_MINCOST; break;#endif default: return error(errServiceUnavailable,"Unknown type-of-service"); } if(setsockopt(so, SOL_IP, IP_TOS,(char *)&tos, (socklen_t)sizeof(tos))) return error(errServiceDenied,"Could not set type-of-service",socket_errno); return errSuccess;#else return error(errServiceUnavailable,"Socket type-of-service not supported",socket_errno);#endif}Socket::Error Socket::setTimeToLiveByFamily(unsigned char ttl, Family fam){ if(!flags.multicast) return error(errMulticastDisabled,"Multicast not enabled on socket"); switch(fam) {#ifdef CCXX_IPV6 case IPV6: flags.ttl = ttl; setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl, sizeof(ttl)); return errSuccess;#endif default:#ifdef IP_MULTICAST_TTL flags.ttl = ttl; setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl)); return errSuccess;#else return error(errServiceUnavailable,"Multicast not supported");#endif }}Socket::Error Socket::setLoopbackByFamily(bool enable, Family family){ unsigned char loop; if(!flags.multicast) return error(errMulticastDisabled,"Multicast not enabled on socket"); if(enable) loop = 1; else loop = 0; flags.loopback = enable; switch(family) {#ifdef CCXX_IPV6 case IPV6: setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&loop, sizeof(loop)); return errSuccess;#endif default: #ifdef IP_MULTICAST_LOOP setsockopt(so, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loop, sizeof(loop)); return errSuccess;#else return error(errServiceUnavailable,"Multicast not supported");#endif }}bool Socket::isPending(Pending pending, timeout_t timeout){ int status;#ifdef USE_POLL struct pollfd pfd; pfd.fd = so; pfd.revents = 0; if(so == INVALID_SOCKET) return true; switch(pending) { case pendingInput: pfd.events = POLLIN; break; case pendingOutput: pfd.events = POLLOUT; break; case pendingError: pfd.events = POLLERR | POLLHUP; break; } status = 0; while(status < 1) { if(timeout == TIMEOUT_INF) status = poll(&pfd, 1, -1); else status = poll(&pfd, 1, timeout); if(status < 1) { // don't stop polling because of a simple // signal :) if(status == -1 && errno == EINTR) continue; return false; } } if(pfd.revents & pfd.events) return true; return false;#else struct timeval tv; struct timeval *tvp = &tv; fd_set grp; if(timeout == TIMEOUT_INF) tvp = NULL; else { tv.tv_usec = (timeout % 1000) * 1000; tv.tv_sec = timeout / 1000; } FD_ZERO(&grp); SOCKET sosave = so; if(so == INVALID_SOCKET) return true; FD_SET(sosave, &grp);#ifdef WIN32 Thread::Cancel cancel = Thread::enterCancel();#endif switch(pending) { case pendingInput: status = select((int)so + 1, &grp, NULL, NULL, tvp); break; case pendingOutput: status = select((int)so + 1, NULL, &grp, NULL, tvp); break; case pendingError: status = select((int)so + 1, NULL, NULL, &grp, tvp); break; }#ifdef WIN32 Thread::exitCancel(cancel);#endif if(status < 1) return false; if(FD_ISSET(so, &grp)) return true; return false;#endif}Socket &Socket::operator=(const Socket &from){ if(so == from.so) return *this; if(state != INITIAL) endSocket(); so = DUP_SOCK(from.so,from.state); if(so == INVALID_SOCKET) { error(errCopyFailed,"Could not duplicate socket handle",socket_errno); state = INITIAL; } else state = from.state; return *this;}void Socket::setCompletion(bool immediate){ flags.completion = immediate;#ifdef WIN32 unsigned long flag; // note that this will not work on some versions of Windows for Workgroups. Tough. -- jfc switch( immediate ) { case false: // this will not work if you are using WSAAsyncSelect or WSAEventSelect. // -- perhaps I should throw an exception flag = 1;// ioctlsocket( so, FIONBIO, (unsigned long *) 1); break; case true: flag = 0;// ioctlsocket( so, FIONBIO, (unsigned long *) 0); break; } ioctlsocket(so, FIONBIO, &flag);#else int fflags = fcntl(so, F_GETFL); switch( immediate ) { case false: fflags |= O_NONBLOCK; fcntl(so, F_SETFL, fflags); break; case true: fflags &=~ O_NONBLOCK; fcntl(so, F_SETFL, fflags); break; }#endif}IPV4Host Socket::getIPV4Sender(tpport_t *port) const{ struct sockaddr_in from; char buf; socklen_t len = sizeof(from); int rc = ::recvfrom(so, &buf, 1, MSG_PEEK, (struct sockaddr *)&from, &len);#ifdef WIN32 if(rc < 1 && WSAGetLastError() != WSAEMSGSIZE) { if(port) *port = 0; memset((void*) &from, 0, sizeof(from)); error(errInput,"Could not read from socket",socket_errno); }#else if(rc < 1) { if(port) *port = 0; memset((void*) &from, 0, sizeof(from)); error(errInput,"Could not read from socket",socket_errno); }#endif else { if(port) *port = ntohs(from.sin_port); } return IPV4Host(from.sin_addr);}#ifdef CCXX_IPV6IPV6Host Socket::getIPV6Sender(tpport_t *port) const{ struct sockaddr_in6 from; char buf; socklen_t len = sizeof(from); int rc = ::recvfrom(so, &buf, 1, MSG_PEEK, (struct sockaddr *)&from, &len);#ifdef WIN32 if(rc < 1 && WSAGetLastError() != WSAEMSGSIZE) { if(port) *port = 0; memset((void*) &from, 0, sizeof(from)); error(errInput,"Could not read from socket",socket_errno); }#else if(rc < 1) { if(port) *port = 0; memset((void*) &from, 0, sizeof(from)); error(errInput,"Could not read from socket",socket_errno); }#endif else { if(port) *port = ntohs(from.sin6_port); } return IPV6Host(from.sin6_addr);}#endifIPV4Host Socket::getIPV4Local(tpport_t *port) const{ struct sockaddr_in addr; socklen_t len = sizeof(addr); if(getsockname(so, (struct sockaddr *)&addr, &len)) { error(errResourceFailure,"Could not get socket address",socket_errno); if(port) *port = 0; memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); } else { if(port) *port = ntohs(addr.sin_port); } return IPV4Host(addr.sin_addr);}#ifdef CCXX_IPV6IPV6Host Socket::getIPV6Local(tpport_t *port) const{ struct sockaddr_in6 addr; socklen_t len = sizeof(addr); if(getsockname(so, (struct sockaddr *)&addr, &len)) { error(errResourceFailure,"Could not get socket address",socket_errno); if(port) *port = 0; memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr)); } else { if(port) *port = ntohs(addr.sin6_port); } return IPV6Host(addr.sin6_addr);}#endifIPV4Host Socket::getIPV4NAT(tpport_t *port) const{ struct sockaddr_in addr; socklen_t len = sizeof(addr); natResult res; if((res=natv4Lookup((int)so, &addr))!=natOK) { if(res==natNotSupported) error( errServiceUnavailable, natErrorString( res ) ); else if(res==natSearchErr) error( errSearchErr, natErrorString( res ) ); else error( errLookupFail, natErrorString( res ), socket_errno ); if(port) *port = 0; memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); } else { if(port) *port = ntohs(addr.sin_port); } return IPV4Host(addr.sin_addr);}#ifdef CCXX_IPV6IPV6Host Socket::getIPV6NAT(tpport_t *port) const{ struct sockaddr_in6 addr; socklen_t len = sizeof(addr); natResult res; if((res=natv6Lookup(so, &addr))!=natOK) { if(res==natNotSupported) error( errServiceUnavailable, natErrorString( res ) ); else if(res==natSearchErr) error( errSearchErr, natErrorString( res ) ); else error( errLookupFail, natErrorString( res ), socket_errno ); if(port) *port = 0; memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr)); } else { if(port) *port = ntohs(addr.sin6_port); } return IPV6Host(addr.sin6_addr);}#endifIPV4Host Socket::getIPV4Peer(tpport_t *port) const{ struct sockaddr_in addr; socklen_t len = sizeof(addr); if(getpeername(so, (struct sockaddr *)&addr, &len)) {#ifndef WIN32 if(errno == ENOTCONN) error(errNotConnected,"Could not get peer address",socket_errno); else#endif error(errResourceFailure,"Could not get peer address",socket_errno); if(port) *port = 0; memset(&addr.sin_addr, 0, sizeof(addr.sin_addr)); } else { if(port) *port = ntohs(addr.sin_port); } return IPV4Host(addr.sin_addr);}#ifdef CCXX_IPV6IPV6Host Socket::getIPV6Peer(tpport_t *port) const{ struct sockaddr_in6 addr; socklen_t len = sizeof(addr); if(getpeername(so, (struct sockaddr *)&addr, &len)) {#ifndef WIN32 if(errno == ENOTCONN) error(errNotConnected,"Could not get peer address",socket_errno); else#endif error(errResourceFailure,"Could not get peer address",socket_errno); if(port) *port = 0; memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr)); } else { if(port) *port = ntohs(addr.sin6_port); } return IPV6Host(addr.sin6_addr);}#endifSocket::Error Socket::setMulticastByFamily(bool enable, Family family){ socklen_t len; switch(family) {#ifdef CCXX_IPV6 case IPV6: struct sockaddr_in6 addr; len = sizeof(addr); if(enable == flags.multicast) return errSuccess; flags.multicast = enable; if(enable) getsockname(so, (struct sockaddr *)&addr, &len); else memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr)); setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&addr.sin6_addr, sizeof(addr.sin6_addr)); return errSuccess;#endif default:#ifdef IP_MULTICAST_IF struct sockaddr_in addr4; len = sizeof(addr4); if(enable == flags.multicast) return errSuccess; flags.multicast = enable; if(enable) getsockname(so, (struct sockaddr *)&addr4, &len); else memset(&addr4.sin_addr, 0, sizeof(addr4.sin_addr)); setsockopt(so, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addr4.sin_addr, sizeof(addr4.sin_addr)); return errSuccess;#else return error(errServiceUnavailable,"Multicast not supported");#endif }}Socket::Error Socket::join(const IPV4Multicast &ia){#ifdef IP_ADD_MEMBERSHIP struct ip_mreq group; struct sockaddr_in myaddr; socklen_t len = sizeof(myaddr); if(!flags.multicast) return error(errMulticastDisabled,"Multicast not enabled on socket"); getsockname(so, (struct sockaddr *)&myaddr, &len); memcpy(&group.imr_interface, &myaddr.sin_addr, sizeof(&myaddr.sin_addr)); group.imr_multiaddr = getaddress(ia); setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)); return errSuccess;#else return error(errServiceUnavailable,"Multicast not supported");#endif}#ifdef CCXX_IPV6Socket::Error Socket::join(const IPV6Multicast &ia){#ifdef IPV6_ADD_MEMBERSHIP struct ipv6_mreq group; struct sockaddr_in6 myaddr; socklen_t len = sizeof(myaddr); if(!flags.multicast) return error(errMulticastDisabled,"Multicast not enabled on socket"); getsockname(so, (struct sockaddr *)&myaddr, &len); memcpy(&group.ipv6mr_interface, &myaddr.sin6_addr, sizeof(&myaddr.sin6_addr)); group.ipv6mr_multiaddr = getaddress(ia); setsockopt(so, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&group, sizeof(group)); return errSuccess;#else return error(errServiceUnavailable,"Multicast not supported");#endif}#endifSocket::Error Socket::drop(const IPV4Multicast &ia){#ifdef IP_DROP_MEMBERSHIP struct ip_mreq group; struct sockaddr_in myaddr; socklen_t len = sizeof(myaddr); if(!flags.multicast) return error(errMulticastDisabled,"Multicast not enabled on socket"); getsockname(so, (struct sockaddr *)&myaddr, &len); memcpy(&group.imr_interface, &myaddr.sin_addr, sizeof(&myaddr.sin_addr)); group.imr_multiaddr = getaddress(ia); setsockopt(so, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&group, sizeof(group)); return errSuccess;#else return error(errServiceUnavailable,"Multicast not supported");#endif}#ifdef CCXX_IPV6Socket::Error Socket::drop(const IPV6Multicast &ia){#ifdef IPV6_DROP_MEMBERSHIP struct ipv6_mreq group; struct sockaddr_in6 myaddr; socklen_t len = sizeof(myaddr); if(!flags.multicast) return error(errMulticastDisabled,"Multicast not enabled on socket"); getsockname(so, (struct sockaddr *)&myaddr, &len); memcpy(&group.ipv6mr_interface, &myaddr.sin6_addr, sizeof(&myaddr.sin6_addr)); group.ipv6mr_multiaddr = getaddress(ia); setsockopt(so, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&group, sizeof(group)); return errSuccess;#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -