📄 xsocket.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 + -