⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket.cpp

📁 贡献一份commoncpp2,有兴趣的可以研究一下
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	return error(errServiceUnavailable,"Multicast not supported");#endif}#endif#ifdef	HAVE_GETADDRINFOUDPSocket::UDPSocket(const char *name, Family fam) :Socket(fam, SOCK_DGRAM, IPPROTO_UDP){	char namebuf[128], *cp;	struct addrinfo hint, *list = NULL, *first;	family = fam;	switch(fam)	{#ifdef	CCXX_IPV6	case IPV6:		peer.ipv6.sin6_family = family;		break;#endif	default:		peer.ipv4.sin_family = family;	}		snprintf(namebuf, sizeof(namebuf), "%s", name);	cp = strrchr(namebuf, '/');	if(!cp && family == IPV4)		cp = strrchr(namebuf, ':');	if(!cp)	{		cp = namebuf;		name = NULL;	}	else	{		name = namebuf;		*(cp++) = 0;		if(!strcmp(name, "*"))			name = NULL;	}	memset(&hint, 0, sizeof(hint));	hint.ai_family = family;	hint.ai_socktype = SOCK_DGRAM;	hint.ai_protocol = IPPROTO_UDP;	hint.ai_flags = AI_PASSIVE;	if(getaddrinfo(name, cp, &hint, &list) || !list)	{		error(errBindingFailed, "Could not find service", errno);		endSocket();		return;	}#if defined(SO_REUSEADDR) && !defined(WIN32)        int opt = 1;        setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,                (socklen_t)sizeof(opt));#endif		first = list;	while(list)	{		if(!bind(so, list->ai_addr, (socklen_t)list->ai_addrlen))		{			state = BOUND;			break;		}		list = list->ai_next;	}	freeaddrinfo(first);	if(state != BOUND)	{		endSocket();		error(errBindingFailed, "Count not bind socket", errno);		return;	}}#elseUDPSocket::UDPSocket(const char *name, Family fam) :Socket(fam, SOCK_DGRAM, IPPROTO_UDP){	char namebuf[128], *cp;	tpport_t port;	struct servent *svc;	socklen_t alen;	struct sockaddr *addr;	family = fam;		snprintf(namebuf, sizeof(namebuf), "%s", name);	cp = strrchr(namebuf, '/');	if(!cp && family == IPV4)		cp = strrchr(namebuf, ':');	if(!cp)	{		cp = namebuf;		name = "*";	}	else	{		name = namebuf;		*(cp++) = 0;	}		if(isdigit(*cp))		port = atoi(cp);	else	{		mutex.enter();		svc = getservbyname(cp, "udp");		if(svc)			port = ntohs(svc->s_port);		mutex.leave();		if(!svc)		{			error(errBindingFailed, "Could not find service", errno);			endSocket();			return;		}	}	struct sockaddr_in addr4;	IPV4Address ia4(name);#ifdef	CCXX_IPV6	struct sockaddr_in6 addr6;	IPV6Address ia6(name);#endif		switch(family)	{#ifdef	CCXX_IPV6	case IPV6:		peer.ipv6.sin6_family = family;		memset(&addr6, 0, sizeof(addr6));		addr6.sin6_family = family;		addr6.sin6_addr = getaddress(ia6);		addr6.sin6_port = htons(port);		alen = sizeof(addr6);		addr = (struct sockaddr *)&addr6;		break;#endif	case IPV4:		peer.ipv4.sin_family = family;		memset(&addr4, 0, sizeof(addr4));		addr4.sin_family = family;		addr4.sin_addr = getaddress(ia4);		addr4.sin_port = htons(port);		alen = sizeof(&addr4);		addr = (struct sockaddr *)&addr4;	}#if defined(SO_REUSEADDR) && !defined(WIN32)        int opt = 1;        setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,                (socklen_t)sizeof(opt));#endif		if(!bind(so, addr, alen))		state = BOUND;	if(state != BOUND)	{		endSocket();		error(errBindingFailed, "Count not bind socket", errno);		return;	}}#endifUDPSocket::UDPSocket(Family fam) :Socket(fam, SOCK_DGRAM, IPPROTO_UDP){	family = fam;	memset(&peer, 0, sizeof(peer));	switch(fam)	{#ifdef	CCXX_IPV6	case IPV6:		peer.ipv6.sin6_family = family;		break;#endif	default:			peer.ipv4.sin_family = family;	}}UDPSocket::UDPSocket(const IPV4Address &ia, tpport_t port) :Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP){	family = IPV4;	memset(&peer.ipv4, 0, sizeof(peer));	peer.ipv4.sin_family = AF_INET;	peer.ipv4.sin_addr = getaddress(ia);	peer.ipv4.sin_port = htons(port);#if defined(SO_REUSEADDR) && !defined(WIN32)	int opt = 1;	setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));#endif	if(bind(so, (struct sockaddr *)&peer.ipv4, sizeof(peer.ipv4)))	{		endSocket();		error(errBindingFailed,"Could not bind socket",socket_errno);		return;	}	state = BOUND;}#ifdef  CCXX_IPV6UDPSocket::UDPSocket(const IPV6Address &ia, tpport_t port) :Socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP){	family = IPV6;	memset(&peer.ipv6, 0, sizeof(peer));	peer.ipv6.sin6_family = AF_INET6;	peer.ipv6.sin6_addr = getaddress(ia);	peer.ipv6.sin6_port = htons(port);#if defined(SO_REUSEADDR) && !defined(WIN32)	int opt = 1;	setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));#endif	if(bind(so, (struct sockaddr *)&peer.ipv6, sizeof(peer.ipv6)))	{		endSocket();		error(errBindingFailed,"Could not bind socket",socket_errno);		return;	}	state = BOUND;}#endifUDPSocket::~UDPSocket(){	endSocket();}ssize_t UDPSocket::send(const void *buf, size_t len){	struct sockaddr *addr;	socklen_t alen;	switch(family)	{#ifdef	CCXX_IPV6	case IPV6:		addr = (struct sockaddr *)&peer.ipv6;		alen = sizeof(struct sockaddr_in6);		break;#endif	case IPV4:		addr = (struct sockaddr *)&peer.ipv4;		alen = sizeof(struct sockaddr_in);	}	if(isConnected())	{		addr = NULL;		alen = 0;	}		return _IORET64 ::sendto(so, (const char *)buf, _IOLEN64 len, 0, addr, alen);}ssize_t UDPSocket::receive(void *buf, size_t len, bool reply){	struct sockaddr *addr;	struct sockaddr_in senderAddress;  // DMC 2/7/05 ADD for use below.	socklen_t alen;	switch(family)	{#ifdef	CCXX_IPV6	case IPV6:		addr = (struct sockaddr *)&peer.ipv6;		alen = sizeof(struct sockaddr_in6);		break;#endif	case IPV4:		addr = (struct sockaddr *)&peer.ipv4;		alen = sizeof(struct sockaddr_in);	}	if(isConnected() || !reply)	{		// DMC 2/7/05 MOD to use senderAddress instead of NULL, to prevent 10014 error		// from recvfrom.		//addr = NULL;		//alen = 0;		addr = (struct sockaddr*)(&senderAddress);		alen = sizeof(struct sockaddr_in);	}		int bytes = ::recvfrom(so, (char *)buf, _IOLEN64 len, 0, addr, &alen);#ifdef	WIN32	int code = 0;	if (bytes == SOCKET_ERROR)	{		code = WSAGetLastError();	}#endif	return _IORET64 bytes;}Socket::Error UDPSocket::join(const IPV4Multicast &ia,int InterfaceIndex){#ifdef WIN32				// DMC 2/7/05: Added WIN32 block.  Win32 does not define the ip_mreqn structure,		// so we must use ip_mreq with INADDR_ANY.		struct ip_mreq      group;        struct sockaddr_in   myaddr;        socklen_t            len = sizeof(myaddr);        if(!flags.multicast)          return error(errMulticastDisabled);	memset(&group, 0, sizeof(group));        getsockname(so, (struct sockaddr *)&myaddr, &len);          group.imr_multiaddr.s_addr = ia.getAddress().s_addr;        group.imr_interface.s_addr = INADDR_ANY;	int retval = setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));	return errSuccess;#elif defined(IP_ADD_MEMBERSHIP) && defined(SIOCGIFINDEX) && !defined(__FreeBSD__) && !defined(_OSF_SOURCE) && !defined(__hpux) && !defined(__GNU__)        		struct ip_mreqn      group;        struct sockaddr_in   myaddr;        socklen_t            len = sizeof(myaddr);        if(!flags.multicast)          return error(errMulticastDisabled);        getsockname(so, (struct sockaddr *)&myaddr, &len);	memset(&group, 0, sizeof(group));        memcpy(&group.imr_address, &myaddr.sin_addr, sizeof(&myaddr.sin_addr));        group.imr_multiaddr = getaddress(ia);        group.imr_ifindex   = InterfaceIndex;        setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));        return errSuccess;#elif defined(IP_ADD_MEMBERSHIP)	// if no by index, use INADDR_ANY	struct ip_mreq group;	struct sockaddr_in myaddr;	socklen_t len = sizeof(myaddr);	if(!flags.multicast)		return error(errMulticastDisabled);	getsockname(so, (struct sockaddr *)&myaddr, &len);	memset(&group, sizeof(group), 0);	group.imr_multiaddr.s_addr = ia.getAddress().s_addr;	group.imr_interface.s_addr = INADDR_ANY;	setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));	return errSuccess;#else        return error(errServiceUnavailable);#endif}Socket::Error UDPSocket::getInterfaceIndex(const char *DeviceName,int& InterfaceIndex){#ifndef WIN32#if defined(IP_ADD_MEMBERSHIP) && defined(SIOCGIFINDEX) && !defined(__FreeBSD__) && !defined(_OSF_SOURCE) && !defined(__hpux) && !defined(__GNU__)  struct ip_mreqn  mreqn;  struct ifreq     m_ifreq;  int              i;  sockaddr*        sa = (sockaddr*) &peer.ipv4;  InterfaceIndex = -1;  mreqn.imr_multiaddr = *(struct in_addr *) &(sa->sa_data[2]);  for (i = 0; i < IFNAMSIZ && DeviceName[i]; ++i)    m_ifreq.ifr_name[i] = DeviceName[i];  for (; i < IFNAMSIZ; ++i)    m_ifreq.ifr_name[i] = 0;  if (ioctl (so, SIOCGIFINDEX, &m_ifreq))    return error(errServiceUnavailable);#if defined(__FreeBSD__) || defined(__GNU__)  InterfaceIndex = m_ifreq.ifr_ifru.ifru_index;#else  InterfaceIndex = m_ifreq.ifr_ifindex;#endif  return errSuccess;#else  return error(errServiceUnavailable);#endif#else  return error(errServiceUnavailable);#endif // WIN32}#ifdef	AF_UNSPECSocket::Error UDPSocket::disconnect(void){	struct sockaddr_in addr;        int len = sizeof(addr);	if(so == INVALID_SOCKET)		return errSuccess;	Socket::state = BOUND;        memset(&addr, 0, len);#ifndef WIN32        addr.sin_family = AF_UNSPEC;#else        addr.sin_family = AF_INET;        addr.sin_addr.s_addr = INADDR_NONE;#endif          if(::connect(so, (sockaddr *)&addr, len))                return connectError();        return errSuccess;}#else   Socket::Error UDPSocket::disconnect(void){	if(so == INVALID_SOCKET)		return errSuccess;	Socket::state = BOUND;        return connect(getLocal());}#endifvoid UDPSocket::setPeer(const IPV4Host &ia, tpport_t port){	memset(&peer.ipv4, 0, sizeof(peer.ipv4));	peer.ipv4.sin_family = AF_INET;	peer.ipv4.sin_addr = getaddress(ia);	peer.ipv4.sin_port = htons(port);}void UDPSocket::connect(const IPV4Host &ia, tpport_t port){	setPeer(ia, port);	if(so == INVALID_SOCKET)		return;	if(!::connect(so, (struct sockaddr *)&peer.ipv4, sizeof(struct sockaddr_in)))		Socket::state = CONNECTED;}#ifdef	CCXX_IPV6void UDPSocket::setPeer(const IPV6Host &ia, tpport_t port){        	memset(&peer.ipv6, 0, sizeof(peer.ipv6));        peer.ipv6.sin6_family = AF_INET6;        peer.ipv6.sin6_addr = getaddress(ia);        peer.ipv6.sin6_port = htons(port);}void UDPSocket::connect(const IPV6Host &ia, tpport_t port){	setPeer(ia, port);	if(so == INVALID_SOCKET)		return;	if(!::connect(so, (struct sockaddr *)&peer.ipv6, sizeof(struct sockaddr_in6)))		Socket::state = CONNECTED;}#endif#ifdef  HAVE_GETADDRINFOvoid UDPSocket::setPeer(const char *name){	char namebuf[128], *cp;	struct addrinfo hint, *list;        snprintf(namebuf, sizeof(namebuf), "%s", name);        cp = strrchr(namebuf, '/');        if(!cp)                cp = strrchr(namebuf, ':');	if(!cp)		return;	memset(&hint, 0, sizeof(hint));	hint.ai_family = family;	hint.ai_socktype = SOCK_DGRAM;	hint.ai_protocol = IPPROTO_UDP;	if(getaddrinfo(namebuf, cp, &hint, &list) || !list)		return;	switch(family)	{#ifdef	CCXX_IPV6	case IPV6:		memcpy(&peer.ipv6, list->ai_addr, sizeof(peer.ipv6));		break;#endif	case IPV4:                memcpy(&peer.ipv4, list->ai_addr, sizeof(peer.ipv4));	}	freeaddrinfo(list);}#elsevoid UDPSocket::setPeer(const char *name){	char namebuf[128], *cp;	struct servent *svc;	tpport_t port;	struct sockaddr *addr;	socklen_t alen;        snprintf(namebuf, sizeof(namebuf), "%s", name);        cp = strrchr(namebuf, '/');        if(!cp)                cp = strrchr(namebuf, ':');	if(!cp)		return;			if(isdigit(*cp))		port = atoi(cp);	else	{		mutex.enter();		svc = getservbyname(cp, "udp");		if(svc)			port = ntohs(svc->s_port);		mutex.leave();		if(!svc)			return;	}		memset(&peer, 0, sizeof(peer));		switch(family)	{#ifdef	CCXX_IPV6	case IPV6:		setPeer(IPV6Host(namebuf), port);		break;#endif	case IPV4:		setPeer(IPV4Host(namebuf), port);	}	}#endifvoid UDPSocket::connect(const char *service){	int rtn;	setPeer(service);	if(so == INVALID_SOCKET)		return;	switch(family)	{#ifdef	CCXX_IPV6	case IPV6:		rtn = ::connect(so, (struct sockaddr *)&peer.ipv6, sizeof(struct sockaddr_in6));		break;#endif	case IPV4:		rtn = ::connect(so, (struct sockaddr *)&peer.ipv4, sizeof(struct sockaddr_in));	}	if(!rtn)		Socket::state = CONNECTED;}IPV4Host UDPSocket::getIPV4Peer(tpport_t *port) const{	// FIXME: insufficient buffer	//        how to retrieve peer ??	char buf;	socklen_t len = sizeof(peer.ipv4);	int rtn = ::recvfrom(so, &buf, 1, MSG_PEEK, (struct sockaddr *)&peer.ipv4, &len);#ifdef WIN32	if(rtn < 1 && WSAGetLastError() != WSAEMSGSIZE)	{		if(port)			*port = 0;		memset((void*) &peer.ipv4, 0, sizeof(peer.ipv4));	}#else	if(rtn < 1)	{		if(port)			*port = 0;		memset((void*) &peer.ipv4, 0, sizeof(peer.ipv4));	}#endif	else	{		if(port)			*port = ntohs(peer.ipv4.sin_port);	}	return IPV4Host(peer.ipv4.sin_addr);}#ifdef  CCXX_IPV6IPV6Host UDPSocket::getIPV6Peer(tpport_t *port) const{	// FIXME: insufficient buffer	//        how to retrieve peer ??	char buf;	socklen_t len = sizeof(peer.ipv6);	int rtn = ::recvfrom(so, &buf, 1, MSG_PEEK, (struct sockaddr *)&peer.ipv6, &len);#ifdef WIN32	if(rtn < 1 && WSAGetLastError() != WSAEMSGSIZE)	{		if(port)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -