标题:服务器能接收信息,而客户端不能?(视频会议代码)
只看楼主
yeyuanzhi
Rank: 1
等 级:禁止访问
帖 子:88
专家分:0
注 册:2005-12-31
结帖率:100%
 问题点数:0 回复次数:0 
服务器能接收信息,而客户端不能?(视频会议代码)
我下载了一个源码.服务器和客户端的CTCP.cpp类都是相同代码:
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 );
}
}



服务器侦听和接受代码:


bool CServer::Run( const int port )
{
if( this->m_server.Create( CServer::OnAccept , this , port ) )
{
  this->logFile.Write( "中央管理服务器初始化成功,正在监听端口 : %d ...\n" , port );
  return true;
}
this->logFile.Write( "中央管理服务器初始化失败\n" );
return false;
}


void CServer::OnAccept( void * wParam , CTCP &server )
{
CServer * pThis = ( CServer * )wParam;
CTCP * client = new CTCP( );
client->SetData( ( int )pThis );
if( server.Accept( client ) )
{
  pThis->logFile.Write( "服务器接收到一个连接\n" );
  CThread::Run( CServer::OnCommand , client );
}
else
{
  client->Close( );
  delete client;
  if( pThis->m_server.IsListen( ) )
  {   
   pThis->logFile.Write( "服务器监听失败,再次启动服务器\n" );
  }
}
}


客户端连接和接收代码:

bool CClient::Run( const char * IP , const int Port )
{
if( this->cmdTCP.Connect( IP , Port ) )
{
  PChannelType cType;
        
  if( cType.assembleData( PChannelType::COMMAND , 0 ) && this->cmdTCP.Send( cType.buffer ) )
  {
   this->serverIP = IP;
   
   this->serverPort = Port;
   ::WriteLog( theApp.GetLogHwnd( ) , ( CString )"连接服务器" + ( CString )IP + ( CString )"成功" );
  }
  else
   this->cmdTCP.Close( );
}
return this->cmdTCP.IsConnected( );
}

void CClient::OnCommand( void * pContext )
{
CClient * pThis = ( CClient * )pContext;
CBuffer buffer;
    //2个数据包之间最大的时间间隔是5分钟
struct timeval tm = { 300 , 0 };
    //无限等待
while( pThis->cmdTCP.Receive( buffer/* , &tm */ ) )
{   //取出数据出错,那么保持连接继续工作
  if( ! buffer.GetSize( ) )
   
   break;
  try
  {
    switch( *( int * )( buffer.GetBuffer( ) + INT_SIZE ) )
   {   //在线用户信息
   case POnlineUserRESTAG : pThis->OnlineUserRES( buffer ); break;
    //创建会议回复
   case PCreateDataNodeRESTAG : pThis->OnCreateDataNodeRES( buffer ); break;
      }
  }
  catch( ... )
  {
  }
}//断开所有连接
pThis->Stop( );
    //写入日志
::WriteLog( theApp.GetLogHwnd( ) , "断开与服务器的连接" );
    //通知界面更新
while( CTipDialog::IsWindow( ) ) ::Sleep( 100 );
//延时5秒钟  
::Sleep( 5000 );
pThis->SendMsg( NULL );
}

//用户注册
int CClient::Register( const char * username , const char * password )
{
int ret =  3;
PRegisterREQ req;
    //组合注册信息
if( req.assembleData( username , password , PRegisterREQ::MEETING ) && this->cmdTCP.Send( req.buffer ) )
{
  CBuffer buffer;
  PRegisterRES res;
        
  if( this->cmdTCP.Receive( buffer ) && res.parseData( buffer ) )
  {
   if( ! res.ireturn )
   {   
   
    //用户注册成功,增加视频通道和声音通道
    PChannelType cType;
    if( this->videoTCP.Connect( this->serverIP.c_str( ) , this->serverPort ) && cType.assembleData( PChannelType::VIDEO , res.user_id ) && this->videoTCP.Send( cType.buffer )
     &&this->audioTCP.Connect( this->serverIP.c_str( ) , this->serverPort ) && cType.assembleData( PChannelType::AUDIO , res.user_id ) && this->audioTCP.Send( cType.buffer ) )
    {   //延时一秒,等待服务器的处理
     ::Sleep( 1000 );
                    //保存用户名和密码
     this->userName = username;
     this->password = password;
     //保存自己在服务器的id
     this->user_id = res.user_id;
     //启动命令线程
     CThread::Run( CClient::OnCommand , this );
     //启动音频线程
     CThread::Run( CClient::OnAudio , this );
                    //启动视频线程
     CThread::Run( CClient::OnVideo , this );
      ::WriteLog( theApp.GetLogHwnd( ) , "注册成功,连接音视频通道" );
   
     ret = 0;
    }
   }
   else
    ret = res.ireturn;
  }
}

服务器能接收到客户端的注册信息.但客户端却接收不了服务器信息.为什么?怎么处理?是不是while( pThis->cmdTCP.Receive( buffer/* , &tm */ ) )有问题?

[[italic] 本帖最后由 yeyuanzhi 于 2007-11-25 14:44 编辑 [/italic]]
搜索更多相关主题的帖子: 视频会议 服务器 客户端 代码 
2007-11-25 14:20



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-188259-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.604539 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved