TCP.cpp
资源名称:视频会议系统.rar [点击查看]
上传用户:popouu88
上传日期:2013-02-11
资源大小:2894k
文件大小:7k
源码类别:
IP电话/视频会议
开发平台:
Visual C++
- // TCP.cpp: implementation of the CTCP class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "TCP.h"
- #include "stdio.h"
- #pragma comment( lib , "ws2_32.lib")
- #define SINGLE_SOCKET 100
- #define MULTI_SOCKET 200
- #define HOST_NAME_LEHGTH 80
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- int CTCP::InitTCPNumber = 0;
- CTCP::CTCP()
- {
- if( CTCP::InitTCPNumber == 0 )
- {
- WSADATA data;
- ::WSAStartup( MAKEWORD( 2 , 1 ) , &data );
- }
- CTCP::InitTCPNumber ++ ;
- this->s_listen = INVALID_SOCKET;
- this->connect_socket = INVALID_SOCKET;
- this->user_data = 0;
- this->visit = 0;
- ::InitializeCriticalSection( &this->session );
- }
- CTCP::~CTCP()
- {
- CTCP::InitTCPNumber -- ;
- if( CTCP::InitTCPNumber == 0 )
- ::WSACleanup( );
- ::DeleteCriticalSection( &this->session );
- }
- char * CTCP::GetIPAddressFromHostName( void )
- {
- char hostname[ HOST_NAME_LEHGTH ];
- ::gethostname( hostname , HOST_NAME_LEHGTH );
- hostent * ent = ::gethostbyname( hostname );
- sockaddr_in addr;
- memcpy( &addr.sin_addr , ent->h_addr , ent->h_length );
- return ::inet_ntoa( *( in_addr * )&addr.sin_addr.s_addr );
- }
- char * CTCP::GetPeerName( void )
- {
- sockaddr_in addr;
- int len = sizeof( addr );
- ::getpeername( this->connect_socket , ( SOCKADDR * )&addr , &len );
- return ::inet_ntoa( *( in_addr * )&addr.sin_addr.s_addr );
- }
- char * CTCP::GetSockName( void )
- {
- sockaddr_in addr;
- int len = sizeof( addr );
- ::getsockname( this->connect_socket , ( SOCKADDR * )&addr , &len );
- return ::inet_ntoa( *( in_addr * )&addr.sin_addr.s_addr );
- }
- bool CTCP::Create( void ( * OnAccept )( void *pContext , CTCP & server ) , void * pContext , const int port )
- {
- if( this == NULL ) return false;
- if( this->IsListen( ) ) return true;
- sockaddr_in addr;
- addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_family=AF_INET;
- addr.sin_port=::htons( port );
- //创建套接字
- SOCKET s = ::socket( AF_INET , SOCK_STREAM , IPPROTO_TCP );
- if(s == INVALID_SOCKET)
- {
- return false;
- }//绑定套接字
- if(::bind( s , ( SOCKADDR * )&addr,sizeof( addr ) ) == SOCKET_ERROR )
- {
- closesocket( s ); return false;
- }//监听套接字
- if( ::listen( s , 5 ) == SOCKET_ERROR )
- {
- closesocket( s ); return false;
- }
- this->s_listen = s;
- CInfo * info = new CInfo( OnAccept , pContext , this );
- CThread::Run( CTCP::OnAccept , info );
- return true;
- }
- void CTCP::OnAccept( void * pContext )
- {
- CInfo * info = ( CInfo * )pContext;
- sockaddr_in addr;
- int len=sizeof(addr);
- for( ; ; )
- {
- if( ( info->pThis->connect_socket = ::accept( info->pThis->s_listen , ( SOCKADDR * )&addr , &len ) ) == INVALID_SOCKET )
- break;
- info->OnAccept( info->pContext , * info->pThis );
- }
- info->pThis->Close( );
- delete info;
- }
- bool CTCP::Accept( CTCP * client )
- {
- if( this == NULL || this->connect_socket == INVALID_SOCKET )
- return false;
- client->connect_socket = this->connect_socket;
- this->connect_socket = INVALID_SOCKET;
- return true;
- }
- bool CTCP::Connect( const char * ip , const port )
- {
- if( this == NULL )
- return false;
- if( this->IsConnected( ) )
- return true;
- sockaddr_in addr;
- addr.sin_addr.s_addr=::inet_addr(ip);
- addr.sin_family=AF_INET;
- addr.sin_port=::htons(port);
- //创建套接字
- if( ( this->connect_socket = ::socket( AF_INET , SOCK_STREAM , IPPROTO_TCP) ) == INVALID_SOCKET )
- return false;
- //连接
- if( ::connect( this->connect_socket , ( SOCKADDR * )&addr , sizeof( addr ) ) == SOCKET_ERROR )
- {
- this->Close( ); return false;
- }
- return true;
- }
- bool CTCP::IsConnected( void )
- {
- return this->connect_socket != INVALID_SOCKET;
- }
- bool CTCP::Send( CBuffer & buffer )
- {
- if( ! this || ! this->IsConnected( ) )
- return false;
- //锁定临界区
- ::EnterCriticalSection( &this->session );
- //保存缓冲区
- int s = 0 , size = *( int * )buffer.GetBuffer( );
- //加密,后面的12个字节都填充ABC,表示头信息
- char * now = buffer.GetBuffer( );
- *( int * )now |= 0xABC00000;
- //分次发送数据包
- fd_set fd;
- FD_ZERO( &fd );
- FD_SET( this->connect_socket , &fd );
- //分次发送
- while( size > 0 && ::select( 0 , NULL , &fd , NULL , NULL ) > 0 && ( s = ::send( this->connect_socket , now , size , 0 ) ) > 0 )
- {
- size -= s;
- now += s;
- }//恢复信息
- *( int * )buffer.GetBuffer( ) ^= 0xABC00000;
- //返回是否连接
- if( size > 0 )
- this->Close( );
- //解锁临界区
- ::LeaveCriticalSection( &this->session );
- return this->IsConnected( );
- }
- bool CTCP::Receive( CBuffer & buffer , struct timeval * timeout )
- {
- if( ! this || ! this->IsConnected( ) )
- return false;
- int s = 0 , size = 1;
- fd_set fd;
- FD_ZERO( &fd );
- FD_SET( this->connect_socket , &fd );
- //接收数据包的大小
- BYTE_INT_UNION BI;
- BI.iValue = 0;
- //一次读取一个字节,读出数据包的大小
- while( ::select( 0 , &fd , NULL , NULL , timeout ) > 0 && ( size & 0xFFF00000 ) != 0xABC00000 )
- {
- BI.B.a = BI.B.b; BI.B.b = BI.B.c; BI.B.c = BI.B.d;
- if( ::recv( this->connect_socket , ( char * )&BI.B.d , ( int )sizeof( BYTE ) , 0 ) <= 0 )
- {
- this->Close( ); break;
- }
- else
- size = BI.iValue;
- }//判断头标志,如果头标志接收错误,那么断开连接
- if( ( size & 0xFFF00000 ) == 0xABC00000 )
- { //取出要接收缓冲区的大小
- size ^= 0xABC00000;
- //重新分配内存
- if( buffer.GetSize( ) < size )
- buffer.Resize( size );
- char * now = buffer.GetBuffer( );
- //保存大小且偏移4个字节
- *( int * )now = size; now += sizeof( int ); size -= sizeof( int );
- //循环接收数据
- while( size > 0 && ::select( 0 , &fd , NULL , NULL , NULL ) > 0 && ( s = ::recv( this->connect_socket , now , size , 0 ) ) > 0 )
- {
- now += s;
- size -= s;
- }
- }//接收过程中出错,那么不处理
- if( size > 0 )
- {
- buffer.Release( );
- size = 1;
- //判断是否可以发送出去
- if( ::send( this->connect_socket , ( char * )&size , ( int )sizeof( char ) , 0 ) <= 0 )
- this->Close( );
- else
- ::Sleep( 100 );
- }//返回是否连接
- return this->IsConnected( );
- }
- void CTCP::Close( void )
- { //关闭监听
- SOCKET s;
- if( this->IsListen( ) )
- {
- s = this->s_listen;
- this->s_listen = INVALID_SOCKET;
- ::closesocket( s );
- }//关闭连接
- if( this->IsConnected( ) )
- {
- s = this->connect_socket;
- this->connect_socket = INVALID_SOCKET;
- ::closesocket( s );
- }
- }