gusucode.com > 嵌入式linux系统的网络编程源码程序 > 嵌入式linux系统的网络编程源码程序/视频会议源码/network_ctrl_send_thread.cpp
/////////////////////////////////////////////////////// // FileName: network_ctrl_send_thread.cpp // Author: b1gm0use // Project: myvideo #include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <qapplication.h> #include <qthread.h> #include <poll.h> #include <qevent.h> #include "network_ctrl_send_thread.h" #include "network_audio_send_thread.h" #include "network_video_send_thread.h" #include "video_cap.h" #include "capture_event.h" #include "video_send.h" #include "network_audio_send.h" #include "network_video_send.h" #include "network_ctrl.h" #include "video.h" #include "network.h" #include "common.h" #include "audio.h" #include "avi.h" #include "signal_def.h" using namespace std; /////////////////////////////////////////////////////// // Public Functions /////////////////////////////////////////////////////// // 构造函数 // 传入参数为 // nc_in 上层network_ctrl对象指针 // stackSize QThread所用的参数 network_ctrl_send_thread::network_ctrl_send_thread ( avi * avi_ptr_in, network_ctrl * nc_in, unsigned int stackSize ) :QThread( stackSize ) // {{{ { verbose_output( 2, "create network_ctrl_send_thread." ); nc = nc_in; fd_ctrl = 0; recv_buff = new BUFF [ PACKET_LENGTH ]; send_buff = new BUFF [ PACKET_LENGTH ]; addr_accept = new sockaddr_in; acclen = new socklen_t; packet_num = 0; expect_num = 0; nast = NULL; nvst = NULL; avi_ptr = avi_ptr_in; client_num = 0; } // }}} // 析构函数 network_ctrl_send_thread::~network_ctrl_send_thread ( void ) // {{{ { if ( 0 != fd_ctrl ) { close( fd_ctrl ); } if ( NULL != nast ) { if ( nast->running() ) { nast->terminate(); cerr << "Warning! Terminate network audio send thread." << endl; } delete nast; } if ( NULL != nvst ) { if ( nvst->running() ) { nvst->terminate(); cerr << "Warning! Terminate network video send thread." << endl; } delete nvst; } delete [] recv_buff; delete [] send_buff; delete addr_accept; delete acclen; } // }}} // 运行部分,线程代码在这里 void network_ctrl_send_thread::run ( void ) // {{{ { verbose_output( 1, "network ctrl send thread running..." ); if ( avi_ptr->use_multicast ) { listen_init_mc(); } else { listen_init(); } if ( avi_ptr->va_mode != AUDIO_ONLY ) { // 使用视频 nvst = new network_video_send_thread( avi_ptr, nc ); nvst->start(); } if ( avi_ptr->va_mode != VIDEO_ONLY ) { // 使用音频 nast = new network_audio_send_thread( avi_ptr, nc ); nast->start(); } if ( avi_ptr->use_multicast ) { listen_handle_mc(); } else { listen_handle(); } return; } // }}} /////////////////////////////////////////////////////// // Private Functions /////////////////////////////////////////////////////// // 连接初始化,创建套接字 void network_ctrl_send_thread::listen_init ( void ) // {{{ { verbose_output( 3, "net_mode LISTEN" ); ///////////////////////////////////////// // 创建控制端口 sockaddr_in addr_listen; socklen_t len = sizeof( addr_listen ); int port = DEFAULT_CTRL_PORT; // 创建一个等待server daemon的监听端口 // 创建控制端监听socket verbose_output( 3, "creating listen socket..." ); fd_ctrl = socket( AF_INET, SOCK_DGRAM, 0 ); // 绑定指定端口 memset( &addr_listen, 0, sizeof( addr_listen ) ); addr_listen.sin_family = AF_INET; addr_listen.sin_addr.s_addr = htonl( INADDR_ANY ); addr_listen.sin_port = htons( port ); // 绑定端口 if ( bind( fd_ctrl, (sockaddr*) & addr_listen, len ) == -1 ) { cerr << "Can't bind to the listen port [" << port << "]" << endl; ::exit( 1 ); } verbose_output( 3, "waiting for connection...", avi_ptr->ip ); *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen ); } // }}} // 处理连接后的数据发送工作 void network_ctrl_send_thread::listen_handle ( void ) // {{{ { // 接收进来的连接 int recv_num; BUFF * buff; bool should_exit = false; int lost_heartbeat = 0; packet_head_t * packet_head = NULL; while ( 1 ) { (*(nc->term_sub_thread_sema))++; should_exit = nc->term_sub_thread; (*(nc->term_sub_thread_sema))--; if ( should_exit ) { cout << "before nast" << endl; nast->wait(); cout << "after nvst" << endl; cout << "before nvst" << endl; nvst->wait(); cout << "after nvst" << endl; QCustomEvent * event = new QCustomEvent( SIG_STOP_OK ); QApplication::postEvent( avi_ptr, event ); return; } // 监听端口 pollfd connect_in = { fd_ctrl, POLLIN, 0 }; int result = poll( &connect_in, 1, DEFAULT_TIMEOUT ); if ( result < 0 ) { perror( "Error in video listening" ); } if ( result == 0 && client_num > 0 ) // {{{ { // 超时,无heartbeat lost_heartbeat++; if ( lost_heartbeat >= MAX_LOST_HEARTBEAT ) { // 客户端丢失 QCustomEvent * event = new QCustomEvent( SIG_LOST_CLIENT ); QApplication::postEvent( avi_ptr, event ); client_num--; nast->wait(); nvst->wait(); return; } } else { // 有数据可读? if ( ( connect_in.revents & POLLIN ) != 0 ) // {{{ { recv_line( fd_ctrl, addr_accept, recv_buff, buff, packet_head ); if ( TEST_CTRL_SYN_BIT( packet_head->opt_bits ) ) { packet_num = recv_num; QCustomEvent * event = new QCustomEvent( SIG_ACCEPT_CONNECT ); QApplication::postEvent( avi_ptr, event ); client_num++; // 写入参数 option_t opt_buf; opt_buf.factor = avi_ptr->video_opt.factor; opt_buf.va_mode = avi_ptr->va_mode; if ( avi_ptr->use_g723 ) { opt_buf.use_g723 = 1; } else { opt_buf.use_g723 = 0; } int length = sizeof( opt_buf ); send_data( fd_ctrl, addr_accept, send_buff, (BUFF *) &opt_buf, length, packet_num, SYN ); verbose_output( 4, "transfer configuration" ); verbose_output( 4, "va_mode\t", avi_ptr->va_mode ); verbose_output( 4, "factor\t", avi_ptr->video_opt.factor ); verbose_output( 4, "use_g723\t", avi_ptr->use_g723 ); } else { if ( TEST_CTRL_HEARTBEAT_BIT( packet_head->opt_bits ) ) { lost_heartbeat = 0; } else { if ( TEST_CTRL_GOODBYE_BIT( packet_head->opt_bits ) ) { // 客户端正常退出 QCustomEvent * event = new QCustomEvent( SIG_ACCEPT_DISCONNECT ); QApplication::postEvent( avi_ptr, event ); nast->wait(); nvst->wait(); client_num--; return; } } } } // if ( ( connect_in.revents & POLLIN ) != 0 ) }}} } // if ( result == 0 ) // }}} } // while ( 1 ) return; } // }}} // 组播初始化,创建套接字 void network_ctrl_send_thread::listen_init_mc ( void ) // {{{ { verbose_output( 3, "network ctrl send thread Multicast init." ); ///////////////////////////////////////// // 创建控制端口 ///////////////////////////////////////// *acclen = sizeof( *addr_accept ); memset( addr_accept, 0, *acclen ); // 网络连接的参数设置 addr_accept->sin_family = AF_INET; addr_accept->sin_port = htons( DEFAULT_MC_CTRL_PORT ); inet_pton( AF_INET, static_cast< const char* >( avi_ptr->mc_addr ), &addr_accept->sin_addr ); // 创建控制端发送socket fd_ctrl = socket( AF_INET, SOCK_DGRAM, 0 ); // 初始化组播 ip_mreq mreq; memcpy( &mreq.imr_multiaddr, &(((sockaddr_in*) addr_accept)->sin_addr), sizeof( in_addr ) ); mreq.imr_interface.s_addr = htonl( INADDR_ANY ); // 加入组播 setsockopt( fd_ctrl, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof( mreq ) ); verbose_output( 3, "ready to send data", avi_ptr->ip ); } // }}} // 处理组播连接后的数据接收工作 void network_ctrl_send_thread::listen_handle_mc ( void ) // {{{ { verbose_output( 3, "network ctrl send thread Multicast handle." ); nast->wait(); cout << "nast wait" << endl; nvst->wait(); cout << "nvst wait" << endl; } // }}}