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

📄 xsocket.cpp

📁 TRIMEDIA DSP 的程序
💻 CPP
字号:
//////////////////////////////////////////////////////////////////////
// XSocket is the base socket class for all xunfei product.
// XSocket include the following functions:
//			CreateUDP/CreateTCPServer/CreateTCPClient/Close
//			Send/Recv
//			Accept
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "XSocket.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

XSocket::XSocket(void *pParent) : m_pParent(pParent)
{
	m_nType = SOCK_TYPE_NULL;
	m_nSock = -1;
	m_bMulticast = FALSE;
}
 
XSocket::~XSocket()
{
	if ( m_nSock>=0 ) {
		closesocket(m_nSock);
		m_nSock = -1;
	}
}

BOOL XSocket::CreateUDPServer(LPCSTR rip, int rport, LPCSTR lip, int lport)
{
    int multicast=0, n=0, ret=0, on=1;
    struct sockaddr_in stLocal, stRemote;
    char *tempaddr, strRemote[256], strLocal[256];

    strcpy(strRemote, rip);
    strcpy(strLocal, lip);
    /* check multicast */
    tempaddr = strchr(strRemote, '.');
    if ( tempaddr==NULL ) return FALSE;
    tempaddr[0] = '\0';
    n = atoi(strRemote);
    if ( n <=0 || n>=255 ) {
//    	TRACE0("Invalid address");
		return FALSE;
    }
    if ( n>=224 ) multicast = 1;
    tempaddr[0] = '.';
   
    /* get a datagram or stream socket */
    m_nSock = socket(AF_INET, SOCK_DGRAM, 0);
    if (m_nSock < 0) {
		m_nSock = -1;
        return FALSE;
    }
    /* avoid EADDRINUSE error on bind() */ 
    ret = setsockopt(m_nSock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
    if (ret < 0 ) {
        closesocket(m_nSock);
		m_nSock = -1;
        return FALSE;
    }

	/* name the socket */
    stLocal.sin_family = AF_INET;
    stLocal.sin_addr.s_addr = inet_addr(strLocal);
    stLocal.sin_port = htons(lport);
    stRemote.sin_family = AF_INET;
    stRemote.sin_addr.s_addr = inet_addr(strRemote);
    stRemote.sin_port = htons(rport);

	ret = bind(m_nSock, (struct sockaddr*)&stLocal, sizeof(stLocal));
	if ( ret < 0 ) {
		closesocket(m_nSock);
		return FALSE;
	}

    if ( multicast ) {
		struct ip_mreq stMreq;
		/* join the multicast group. */
	  	stMreq.imr_multiaddr.s_addr = inet_addr(strRemote);
        stMreq.imr_interface.s_addr = inet_addr(strLocal);
        ret = setsockopt(m_nSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
        if ( ret < 0 ) {
            //dbg_print1("<FATAL ERROR> ","setsockopt() IP_ADD_MEMBERSHIP failed, Err: %d\n",errno);
            closesocket(m_nSock);
			m_nSock = -1;
            return FALSE;
        } 
        /* set TTL to traverse up to multiple routers */
        on = TTL_VALUE;
        ret = setsockopt(m_nSock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&on, sizeof(on));
        if ( ret < 0 ) {
            //dbg_print1("<FATAL ERROR> ","setsockopt() IP_MULTICAST_TTL failed, Err: %d\n", errno);
            closesocket(m_nSock);
			m_nSock = -1;
            return FALSE;
        }
        /* enable loopback for multicast, but not valid in windows platform*/
        on  = TRUE;
        ret = setsockopt(m_nSock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&on, sizeof(on));
        if ( ret < 0 ) {
            //dbg_print1("<FATAL ERROR> ","setsockopt() IP_MULTICAST_LOOP failed, Err: %d\n",errno);
        }
    }
    	
    memcpy(&m_UDPAddr, &stRemote,sizeof(stRemote));
	m_bMulticast = multicast==1;
	
    m_nType = SOCK_TYPE_UNICAST_UDP_SERVER;
    return TRUE;
}

BOOL XSocket::CreateUDPClient(LPCSTR rip, int rport, LPCSTR lip, int lport)
{
    int multicast=0, n=0, ret=0, on=1;
    struct sockaddr_in stLocal;
    char *tempaddr, strRemote[256], strLocal[256];

    strcpy(strRemote, rip);
    strcpy(strLocal, lip);
    /* check multicast */
    tempaddr = strchr(strRemote, '.');
    if ( tempaddr==NULL ) return FALSE;
    tempaddr[0] = '\0';
    n = atoi(strRemote);
    if ( n <0 || n>=255 ) {
//    	TRACE0("Invalid address");
		return FALSE;
    }
    if ( n>=224 ) multicast = 1;
    tempaddr[0] = '.';
   
    /* get a datagram or stream socket */
    m_nSock = socket(AF_INET, SOCK_DGRAM, 0);
    if (m_nSock < 0) {
		m_nSock = -1;
        return FALSE;
    }
    /* avoid EADDRINUSE error on bind() */ 
    ret = setsockopt(m_nSock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
    if (ret < 0 ) {
        closesocket(m_nSock);
		m_nSock = -1;
        return FALSE;
    }

	/* name the socket */
	stLocal.sin_family = AF_INET;
	stLocal.sin_addr.s_addr = inet_addr(strLocal);
	stLocal.sin_port = htons(lport);
	
	ret = bind(m_nSock, (struct sockaddr*)&stLocal, sizeof(stLocal));
	if ( ret < 0 ) {
		//dbg_print1("<FATAL ERROR> ","bind() failed, Err: %d\n", errno );
		closesocket(m_nSock);
		m_nSock = -1;
		return FALSE;
	}

    if ( multicast ) {
		struct ip_mreq stMreq;
		/* join the multicast group. */
	  	stMreq.imr_multiaddr.s_addr = inet_addr(strRemote);
        stMreq.imr_interface.s_addr = inet_addr(strLocal);
        ret = setsockopt(m_nSock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq));
        if ( ret < 0 ) {
            //dbg_print1("<FATAL ERROR> ","setsockopt() IP_ADD_MEMBERSHIP failed, Err: %d\n",errno);
            closesocket(m_nSock);
			m_nSock = -1;
            return FALSE;
        } 
        /* set TTL to traverse up to multiple routers */
        on = TTL_VALUE;
        ret = setsockopt(m_nSock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&on, sizeof(on));
        if ( ret < 0 ) {
            //dbg_print1("<FATAL ERROR> ","setsockopt() IP_MULTICAST_TTL failed, Err: %d\n", errno);
            closesocket(m_nSock);
			m_nSock = -1;
            return FALSE;
        }
        /* enable loopback for multicast, but not valid in windows platform*/
        on  = TRUE;
        ret = setsockopt(m_nSock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&on, sizeof(on));
        if ( ret < 0 ) {
            //dbg_print1("<FATAL ERROR> ","setsockopt() IP_MULTICAST_LOOP failed, Err: %d\n",errno);
        }
    }
	
    m_nType = SOCK_TYPE_UNICAST_UDP_CLIENT;
    return TRUE;
}

BOOL XSocket::CreateTCPServer(LPCSTR lip, int port)
{
	struct sockaddr_in addr;
	int on=1;
	m_nSock = socket(AF_INET, SOCK_STREAM, 0);
	if( m_nSock == INVALID_SOCKET ) {
		m_nSock = -1;
		return FALSE;
	}
	addr.sin_family = AF_INET;
//	if( strcmp(lip, "0.0.0.0") == 0 )
//		addr.sin_addr.s_addr = INADDR_ANY;//htonl(INADDR_ANY);
//	else
//		addr.sin_addr.s_addr = inet_addr(lip);
	addr.sin_addr.s_addr = INADDR_ANY;//htonl(INADDR_ANY);
	addr.sin_port = htons(port);
	int result = setsockopt(m_nSock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
	if( bind(m_nSock, (sockaddr *)&addr, sizeof(sockaddr_in)) == SOCKET_ERROR )	{	
		closesocket(m_nSock);	
		m_nSock = -1;
		return FALSE;	
	}
	if( listen(m_nSock, MAX_LISTEN_QUEUE ) == SOCKET_ERROR ){
		closesocket(m_nSock);	
		m_nSock = -1;
		return FALSE;	
	}

	m_nType = SOCK_TYPE_UNICAST_TCP_SERVER;
	return TRUE;
}

BOOL XSocket::CreateTCPClient(LPCSTR rip, int rport)
{
	struct sockaddr_in addr;
	int on=1;
	m_nSock = socket(AF_INET, SOCK_STREAM, 0);
	if( m_nSock < 0 ) {
		m_nSock = -1;
		return FALSE;
	}
	int result = setsockopt(m_nSock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
	if (result < 0 ) {
		closesocket(m_nSock);
		m_nSock = -1;
		return FALSE;
	}
	on=1;
	result = setsockopt(m_nSock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on)); //not use Nagle delay algorithm
	result = setsockopt(m_nSock, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on)); //keep alive in TCP connection
	
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(rip);//htonl(m_sHostIp);
	addr.sin_port = htons(rport);
	result = connect(m_nSock, (sockaddr *)&addr, sizeof(sockaddr));
	if( result != 0 ){
		closesocket(m_nSock);
		m_nSock = -1;
		return FALSE;
	}
	m_nType = SOCK_TYPE_UNICAST_TCP_CLIENT;
	return TRUE;
}

XSocket* XSocket::Accept()
{
	SOCKET nNewSocket;
	XSocket *pNewSocket = NULL;
	if( m_nType!=SOCK_TYPE_UNICAST_TCP_SERVER || m_nSock < 0 ) {
		TRACE0("No Valid Socket\n");
		return NULL;
	}
	if(( nNewSocket = accept(m_nSock, NULL, 0)) ==INVALID_SOCKET ) {	// Accept an incoming connection
		int Err_res = WSAGetLastError();
		return NULL;
	}
	pNewSocket = new XSocket;		// Create a new VSocket and return it
	if( pNewSocket != NULL) {	
		const int one = 1;
		pNewSocket->m_nSock = nNewSocket;
		pNewSocket->m_nType = SOCK_TYPE_UNICAST_TCP_CLIENT;
		// Attempt to set the new socket's options
		setsockopt(pNewSocket->m_nSock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one));
	} else {
		shutdown(nNewSocket, SD_BOTH);
		closesocket(nNewSocket);
	}
	return pNewSocket;
}

BOOL XSocket::Close()
{
	if( m_nType == SOCK_TYPE_NULL ) return FALSE;

	shutdown(m_nSock, SD_BOTH);
	closesocket(m_nSock);
	m_nSock = -1;
	m_bMulticast = FALSE;
	
	m_nType = SOCK_TYPE_NULL;

	return TRUE;
}

int XSocket::Send(char *buf, int len)
{
	// if m_nSock is closed, return bytes is -1
	int bytes=-1;
	if( m_nType == SOCK_TYPE_UNICAST_UDP_SERVER ) {
		bytes = sendto(m_nSock, buf, len, 0, 
			(struct sockaddr*)&m_UDPAddr, sizeof(m_UDPAddr) );
	}
	else if( m_nType == SOCK_TYPE_UNICAST_TCP_CLIENT ) {
		int length=len;
		do {
			bytes = send(m_nSock, buf, length, 0);
			if ( bytes>0 ) {
				length-=bytes;
				buf+=bytes;
			}
		} while ( length>0 && bytes>0 );
		if ( length==0 )	bytes = len; // 已发送的字节数
	}
	else {
		TRACE0("XSocket Send Error\n");
	}
	return bytes;
}

int XSocket::Recv(char *buf, int len)
{
	int bytes = -1;
	if( m_nType == SOCK_TYPE_UNICAST_UDP_CLIENT ) {
		bytes = recvfrom(m_nSock, buf, len, 0, 
			NULL, NULL);
	}
	else if( m_nType == SOCK_TYPE_UNICAST_TCP_CLIENT )  {
		int length=len;
		do {
			bytes = recv(m_nSock, buf, length, 0);
			if ( bytes>0 ) {
				length-=bytes;
				buf+=bytes;
			}
		} while ( length>0 && bytes>0 );
		if ( length==0 )	bytes = len; // 已接收的字节数
	}
	else {
		TRACE0("XSocket Recv Error\n");
	}
	return bytes;
}

int XSocket::RecvBytes(char *buf, int len)
{
	int bytes = -1;
	if( m_nType == SOCK_TYPE_UNICAST_UDP_CLIENT ) {
		bytes = recvfrom(m_nSock, buf, len, 0, 
			NULL, NULL);
	}
	else if( m_nType == SOCK_TYPE_UNICAST_TCP_CLIENT ) {
		bytes = recv(m_nSock, buf, len, 0);
		return bytes;
	}
	else {
		TRACE0("XSocket Recv Error\n");
	}
	return bytes;
}

BOOL XSocket::SetReceiveBuffer(int nLength)
{//original is 8*1024
	if ( m_nSock==-1 ) return FALSE;
	return setsockopt(m_nSock, SOL_SOCKET, SO_RCVBUF, (char*)&nLength, sizeof(nLength))==0;
}

BOOL XSocket::SetSendBuffer(int nLength)
{//original is 8*1024
	if ( m_nSock==-1 ) return FALSE;
	return setsockopt(m_nSock, SOL_SOCKET, SO_SNDBUF, (char*)&nLength, sizeof(nLength))==0;
}

BOOL XSocket::GetSockName(char *sockAddr, int *port)
{
	if( m_nSock < 0 ) return FALSE;
#define MAXADDRLEN 256
	union{
		struct sockaddr_in addr;
		char data[MAXADDRLEN];
	}un;
	int len = MAXADDRLEN;
	if( getsockname(m_nSock, (struct sockaddr*)un.data, &len) < 0 )
		return FALSE;
	//copy addr to string
	*port = ntohs(un.addr.sin_port);
	char *pAddr = inet_ntoa(un.addr.sin_addr);
	if( pAddr == NULL ) return FALSE;
	strcpy(sockAddr, pAddr);
	return TRUE;
}

int XSocket::CheckReadable(int timeout)
{
	m_tv.tv_sec = timeout;
	m_tv.tv_usec = 0;
	FD_ZERO(&m_readfds);
	FD_SET(m_nSock, &m_readfds);
	return select(m_nSock+1, &m_readfds, NULL, NULL, &m_tv);
}

⌨️ 快捷键说明

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