📄 cconnection.cpp
字号:
/******************************************************************************
* Copyright (c) 2009 xxx Electronics, Inc.
* All rights reserved.
*-----------------------------------------------------------------------------
* Description:
* CConection class 连接处理
* CError class 错误处理
* CNetworking class 端口监听以及远程计算机信息获取
* CSync class 线程同步处理
* CThreadManager class 线程创建、线程状态监控、线程释放
* CAcquisition class 实时数据采集
*
* Change History:
* 04/26/2009 Chen Jian 添加注释规范代码、修正线程泄漏问题、添加错误处理
* Comments: 支持多个连接通讯
*
******************************************************************************/
#include "CConnection.h"
#define BACKLOG 10 // 等待联接的最大队列长度
#define TIMEOUT 2 // sec
#define RECVSIZE 1024 // 接收缓存
#define MAX_CONNECT_LEN 512
long CNetworking::m_count = 0;
CNetworking::CNetworking () : m_lasterror ( )
{
if ( m_count == 0 && CConnection::m_count == 0 )
{
WSADATA wsd;
int err;
err = WSAStartup ( MAKEWORD ( 1, 1 ), &wsd );
if ( err != 0 )
CError::GetErrorString ( err );
}
m_hAcceptEvent = NULL;
m_hAcceptFunc = NULL;
m_dwAcceptThreadID = 0;
m_hAcceptThread = NULL;
m_socket = INVALID_SOCKET;
m_count ++;
}
CNetworking::~CNetworking ()
{
StopListen ();
if ( m_count == 1 && CConnection::m_count == 0 )
WSACleanup();
m_count --;
}
bool CNetworking::Listen ( int port )
{
int flag = 1;
int len = sizeof ( int );
if ( IsListening () )
StopListen ();
sockaddr_in addr;
SOCKET sock;
sock = socket ( AF_INET, SOCK_STREAM, 0 );
addr.sin_family = AF_INET;
addr.sin_port = htons ( port );
addr.sin_addr.s_addr = htonl ( INADDR_ANY );
if ( bind ( sock, ( LPSOCKADDR ) &addr, sizeof ( addr ) ) == SOCKET_ERROR )
{
closesocket ( sock );
long err = WSAGetLastError ();
CError::GetErrorString ( err );
return false;
}
if ( listen ( sock, BACKLOG ) < 0 )
{
closesocket ( sock );
long err = WSAGetLastError ();
CError::GetErrorString ( err );
return false;
}
m_sync.Lock ();
m_socket = sock;
m_addr = addr;
m_sync.UnLock ();
m_hAcceptThread = CreateThread ( NULL,
0,
( LPTHREAD_START_ROUTINE ) AcceptThread,
this,
0,
( LPDWORD ) & m_dwAcceptThreadID );
if ( !m_hAcceptThread )
{
StopListen ();
return false;
}
return true;
}
void CNetworking::StopListen ()
{
if ( !IsListening () )
{
CError::GetErrorString ( WSAENOTCONN );
return;
}
m_sync.Lock ();
closesocket ( m_socket );
m_socket = INVALID_SOCKET;
m_sync.UnLock ();
WaitForSingleObject ( m_hAcceptThread, INFINITE );
CloseHandle ( m_hAcceptThread );
m_hAcceptThread = NULL;
}
void CNetworking::SetAcceptFunc ( CALLBACKFUNC hFunc )
{
m_sync.Lock ();
m_hAcceptFunc = hFunc;
m_sync.UnLock ();
}
void CNetworking::SetAcceptEvent ( HANDLE hEvent )
{
m_sync.Lock ();
m_hAcceptEvent = hEvent;
m_sync.UnLock ();
}
CConnection* CNetworking::GetAccepted ()
{
CConnection* cAccepted;
m_sync.Lock ();
cAccepted = m_accepted.Remove ();
m_sync.UnLock ();
return cAccepted;
}
int CNetworking::HasAccepted ()
{
int iAccepted;
m_sync.Lock ();
iAccepted = m_accepted.Length ();
m_sync.UnLock ();
return iAccepted;
}
bool CNetworking::IsListening ()
{
bool bListening;
m_sync.Lock ();
bListening = m_socket != INVALID_SOCKET;
m_sync.UnLock ();
return bListening;
}
int CNetworking::AcceptWait ()
{
int addr_size = sizeof ( sockaddr_in );
SOCKET lsock;
SOCKET csock = INVALID_SOCKET;
sockaddr_in caddr = { 0 };
m_sync.Lock ();
lsock = m_socket;
m_sync.UnLock ();
while ( IsListening () )
{
m_sync.Lock ();
bool bRightSock = ( lsock == m_socket );
m_sync.UnLock ();
if ( !bRightSock ) return 1;
csock = accept ( lsock, ( LPSOCKADDR ) & caddr, &addr_size );
if ( csock == INVALID_SOCKET )
{
int aErr = WSAGetLastError();
if ( aErr == WSAEINTR )
{
StopListen ();
return 1;
}
else
{
long err = WSAGetLastError ();
CError::GetErrorString ( err );
StopListen ();
return 1;
}
}
else
{
CConnection* cAccepted = new CConnection ();
cAccepted->m_socket = csock;
cAccepted->m_addr = caddr;
cAccepted->m_hRecvThread = CreateThread ( NULL,
0,
( LPTHREAD_START_ROUTINE ) cAccepted->RecvThread,
cAccepted,
0,
( LPDWORD ) & cAccepted->m_dwRecvThreadID );
if ( cAccepted->m_hRecvThread == NULL )
{
//cAccepted->Disconnect ();
delete cAccepted;
CError::GetErrorString ( 1002 );
}
else
{
m_sync.Lock ();
m_accepted.Add ( cAccepted );
HANDLE hEvent = m_hAcceptEvent;
CALLBACKFUNC fncCallback = m_hAcceptFunc;
m_sync.UnLock ();
if ( hEvent ) SetEvent ( hEvent );
if ( fncCallback ) ( fncCallback ) ( ( DWORD ) this );
}
}
}
return 0;
}
int CNetworking::AcceptThread ( void* pThis )
{
return ( ( CNetworking* ) ( pThis ) )->AcceptWait ();
}
bool CNetworking::GetLocalName ( char *localname, int len )
{
char locname[512] = "";
int status = gethostname ( locname, 512 );
if ( status != 0 )
{
long err = WSAGetLastError ();
CError::GetErrorString ( err );
return false;
}
memset ( localname, 0, len );
int uselen = strlen ( locname ) + 1;
if ( uselen > len ) uselen = len;
memcpy ( localname, locname, uselen );
return true;
}
bool CNetworking::GetLocalIP ( char *localip, int len )
{
char locname[512];
char locip[16];
if ( ! ( GetLocalName ( locname, 512 ) && ResolveIP ( locname, locip, 16 ) ) )
return false;
memset ( localip, 0, len );
int uselen = strlen ( locip ) + 1;
if ( len < uselen ) uselen = len;
memcpy ( localip, locip, uselen );
return true;
}
bool CNetworking::GetLocalIPs ( char *localips, int len )
{
char locname[512] = "";
char locips[256] = "";
if ( !GetLocalName ( locname, 512 ) || !ResolveIPs ( locname, locips, 256 ) )
return false;
memset ( localips, 0, len );
int uselen = strlen ( locips ) + 1;
if ( len < uselen ) uselen = len;
memcpy ( localips, locips, uselen );
return true;
}
bool CNetworking::ResolveName ( char *hostip, char *hostname, int len )
{
unsigned long hstaddr = inet_addr ( hostip );
hostent* phe = gethostbyaddr ( ( char* ) & hstaddr, sizeof ( unsigned long ), AF_INET );
if ( phe == NULL )
{
long err = WSAGetLastError ();
CError::GetErrorString ( err );
return false;
}
char *hstname = ( char* ) phe->h_name;
memset ( hostname, 0, len );
int uselen = strlen ( hstname ) + 1;
if ( len < uselen ) uselen = len;
memcpy ( hostname, hstname, uselen );
return true;
}
bool CNetworking::ResolveIP ( char *hostname, char *hostip, int len )
{
hostent* phe = gethostbyname ( hostname );
if ( phe == NULL )
{
long err = WSAGetLastError ();
CError::GetErrorString ( err );
return false;
}
char hstip[15] = "";
if ( phe->h_addr_list[0] != NULL )
{
sprintf ( hstip, "%u.%u.%u.%u",
( unsigned char ) phe->h_addr_list[0][0],
( unsigned char ) phe->h_addr_list[0][1],
( unsigned char ) phe->h_addr_list[0][2],
( unsigned char ) phe->h_addr_list[0][3] );
}
else
{
long err = WSAGetLastError ();
CError::GetErrorString ( err );
return false;
}
memset ( hostip, 0, len );
int uselen = strlen ( hstip ) + 1;
if ( len < uselen ) uselen = len;
memcpy ( hostip, hstip, uselen );
return true;
}
bool CNetworking::ResolveIPs ( char *hostname, char *hostips, int len )
{
hostent *phe = gethostbyname ( hostname );
char allips[256], null_ip[256];
if ( phe == NULL || phe->h_addr_list[0] == NULL )
{
long err = WSAGetLastError ();
CError::GetErrorString ( err );
return false;
}
int count = 0,
i = 0;
for ( i = 0; i < 256; i++ )
{
allips[i] = 0;
null_ip[i] = 0;
}
while ( phe->h_addr_list[count] != NULL && count * 15 < 240 )
{
char oneip[15] = "";
for ( i = 0; i < 15; i++ )
oneip[i] = 0;
sprintf ( oneip, "%u.%u.%u.%u",
( unsigned char ) phe->h_addr_list[count][0],
( unsigned char ) phe->h_addr_list[count][1],
( unsigned char ) phe->h_addr_list[count][2],
( unsigned char ) phe->h_addr_list[count][3] );
for ( i = ( count * 15 ); i < ( count * 15 + 15 ); i++ )
null_ip[i] = oneip[i % 15];
count++;
}
int lEnd = 0;
for ( i = 0; i < 15; i++ )
{
if ( null_ip[i * 15] == 0 ) break;
for ( int j = 0; j < 15; j++ )
allips[lEnd + j] = null_ip[i * 15 + j];
lEnd = strlen ( allips );
allips[lEnd] = 13;
lEnd ++;
}
for ( i = 0; i < len; i++ )
hostips[i] = 0;
int uselen = strlen ( allips );
if ( uselen > len ) uselen = len;
for ( i = 0; i < uselen; i++ )
hostips[i] = allips[i];
hostips[uselen] = 0;
return true;
}
long CConnection::m_count = 0;
CConnection::CConnection ()
{
if ( m_count == 0 && CNetworking::m_count == 0 )
{
WSADATA wsd;
int err;
err = WSAStartup ( MAKEWORD ( 1, 1 ), &wsd );
if ( err != 0 )
CError::GetErrorString ( err );
}
m_event = CreateEvent ( NULL, TRUE, FALSE, NULL );
m_hCloseEvent = NULL;
m_hCloseFunc = NULL;
m_hRecvEvent = NULL;
m_hRecvFunc = NULL;
m_dwRecvThreadID = 0;
m_hRecvThread = NULL;
m_socket = INVALID_SOCKET;
m_count ++;
}
CConnection::CConnection ( const char* host, unsigned short port )
{
if ( m_count == 0 && CNetworking::m_count == 0 )
{
WSADATA wsd;
int err;
err = WSAStartup ( MAKEWORD ( 1, 1 ), &wsd );
if ( err != 0 )
CError::GetErrorString ( err );
}
m_event = CreateEvent ( NULL, TRUE, FALSE, NULL );
m_hCloseEvent = NULL;
m_hCloseFunc = NULL;
m_hRecvEvent = NULL;
m_hRecvFunc = NULL;
m_dwRecvThreadID = 0;
m_hRecvThread = NULL;
m_socket = INVALID_SOCKET;
m_count ++;
if ( !Connect ( host, port ) )
{
long err = WSAGetLastError ();
if ( err == 0 )
CError::GetErrorString ( err );
}
}
CConnection::~CConnection ()
{
Disconnect ();
if ( m_count == 1 && CNetworking::m_count == 0 )
WSACleanup();
CloseHandle ( m_event );
m_count --;
}
bool CConnection::Connect ( const char* host, unsigned short port )
{
Disconnect ();
sockaddr_in addr;
SOCKET sock;
sock = socket ( AF_INET, SOCK_STREAM, 0 );
addr.sin_family = AF_INET;
addr.sin_port = htons ( port );
addr.sin_addr.s_addr = inet_addr ( host );
if ( connect ( sock, ( LPSOCKADDR ) &addr, sizeof ( addr ) ) == SOCKET_ERROR )
{
long err = WSAGetLastError ();
CError::GetErrorString ( err );
return false;
}
linger lg;
lg.l_onoff = 1;
lg.l_linger = 10;
setsockopt ( sock, SOL_SOCKET, SO_LINGER, reinterpret_cast <const char*> ( &lg ), sizeof ( linger ) );
m_hRecvThread = CreateThread ( NULL,
0,
( LPTHREAD_START_ROUTINE ) RecvThread,
this,
0,
( LPDWORD ) & m_dwRecvThreadID );
if ( m_hRecvThread == NULL )
{
CError::GetErrorString ( 1002 );
closesocket ( sock );
return false;
}
m_sync.Lock ();
m_socket = sock;
m_addr = addr;
m_sync.UnLock ();
return true;
}
void CConnection::Disconnect ()
{
if ( !IsConnected () )
{
CError::GetErrorString ( WSAENOTCONN );
return;
}
int status;
fd_set readfds;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -