pjsip学习 ------ 二

pjsip中最基础也是最重要的,我认为有两个,一个是pj_ioqueue  ,一个是pj_timer .

这次我要说一下 ioqueue .

pjsip中的ioqueue 是一个异步的,可支持并发操作的队列。主要运用于socket收发消息。再个个平台,它的底层实现是不同的。 有这么几种。 

 1 .I/O Completion ports ( Windows NT/2000/XP)

2 /dev/epoll (linux)   

3 select()

下面我通过一个例子程序来说一下pj_ioqueue的创建 使用。 这个例子程序有两部分。server 端 和 client 端。 client端 发送随机字符串,server端打印出来。

server.c

#include "pjlib.h"

typedef  struct  test_op_key{
	pj_ioqueue_op_key_t  op_key ;
	char  data[200] ;
}test_op_key ;


static void on_ioqueue_read( pj_ioqueue_key_t  *key , pj_ioqueue_op_key_t  * op_key , 
				pj_ssize_t  bytes_read) 
{
	PJ_LOG(3 , ("read " ,"read %d" , bytes_read )) ; 
	test_op_key  *tt_key = (test_op_key*)op_key ;
	PJ_LOG(3 , ("read " ,"read %s" , tt_key->data )) ;
}

static void on_ioqueue_write( pj_ioqueue_key_t *key , pj_ioqueue_op_key_t  *op_key , 
				pj_ssize_t  bytes_written) 
{

	PJ_LOG(3 , ("wirte " , "%d" , bytes_written)) ;

}

static void on_ioqueue_accept( pj_ioqueue_key_t *key , pj_ioqueue_op_key_t  *op_key ,
				pj_sock_t  sock , int status )
{

}

static void on_ioqueue_connect (pj_ioqueue_key_t *key , int status ) 
{


}
static  pj_ioqueue_callback  test_cb = {

	&on_ioqueue_read ,
	&on_ioqueue_write ,
	&on_ioqueue_accept , 
	&on_ioqueue_connect ,
};
//回调函数组
int  main()
{

	pj_status_t   status ;
	pj_caching_pool  cp ;	
	pj_pool_t       *pool ;
	pj_sock_t  ssock = -1 ,csock = -1 ;
	pj_sockaddr_in   addr ;
	pj_ioqueue_t  *ioque = NULL ;
	pj_ioqueue_key_t  *skey   ;
	test_op_key    read_op ;	
	pj_ssize_t  bytes ;
	status = pj_init();
	if(status != PJ_SUCCESS )
	{
		printf("error init ");	
		return -1 ;
	}

	pj_caching_pool_init(&cp , NULL , 0 ) ;
	
	pool = pj_pool_create( &cp.factory , NULL , 1024 , 1024 , NULL ) ;
	pj_sock_socket( pj_AF_INET() , pj_SOCK_DGRAM() , 0 , &ssock ) ;
	pj_sock_socket( pj_AF_INET() , pj_SOCK_DGRAM() , 0 , &csock ) ;

	pj_bzero(&addr , sizeof(addr) );
	
	pj_str_t  s ;
	addr.sin_family = pj_AF_INET();
	addr.sin_port = pj_htons(34780) ;
	addr.sin_addr = pj_inet_addr(pj_cstr(&s , "127.0.0.1" )) ;
	pj_sock_bind( ssock , &addr , sizeof(addr));
	pj_ioqueue_create(pool , PJ_IOQUEUE_MAX_HANDLES , &ioque ) ;    //创建queue
	pj_ioqueue_register_sock(pool , ioque , ssock , NULL , &test_cb , &skey ) ;  //r注册socket 到queue
	pj_bzero(&addr , sizeof(addr)) ;
	int addrlen =  sizeof(addr ) ;
	bytes = 200 ; 
	do{
		pj_time_val timeout = { 1 , 0 } ;
		status = pj_ioqueue_poll ( ioque , &timeout ) ; //poll  queue
		status =pj_ioqueue_recvfrom(skey , &(read_op.op_key) , read_op.data , &bytes , 0 ,&addr ,&addrlen ) ;
       // 注意 recv 的第二第三个参数。 我放到test_op_key结构体中了,这样当回调的时候,就能取出收到的数据。

	}while(1) ;		 

	pj_caching_pool_destroy(&cp) ;
	
	pj_shutdown();

	return 0 ;
	


}


client.c


#include "pjlib.h"

static void on_ioqueue_read( pj_ioqueue_key_t  *key , pj_ioqueue_op_key_t  * op_key , 
				pj_ssize_t  bytes_read) 
{
	PJ_LOG(3 , ("read " ,"read %d" , bytes_read )) ;		
}

static void on_ioqueue_write( pj_ioqueue_key_t *key , pj_ioqueue_op_key_t  *op_key , 
				pj_ssize_t  bytes_written) 
{

	  PJ_LOG(3 , ("wirte " , "%d" , bytes_written)) ;


}

static void on_ioqueue_accept( pj_ioqueue_key_t *key , pj_ioqueue_op_key_t  *op_key ,
				pj_sock_t  sock , int status )
{




}

static void on_ioqueue_connect (pj_ioqueue_key_t *key , int status ) 
{


}
static  pj_ioqueue_callback  test_cb = {

	&on_ioqueue_read ,
	&on_ioqueue_write ,
	&on_ioqueue_accept , 
	&on_ioqueue_connect ,
};

int  main()
{

	pj_status_t   status ;
	pj_caching_pool  cp ;	
	pj_pool_t       *pool ;
	pj_sock_t  ssock = -1 ,csock = -1 ;
	pj_sockaddr_in   addr ,dst_addr ;
       
	char * send_buf  ;
	pj_ioqueue_t  *ioque = NULL ;
	pj_ioqueue_key_t   *ckey ;
        pj_ioqueue_op_key_t  write_op ;
	pj_ssize_t  bytes ;
	status = pj_init();
	if(status != PJ_SUCCESS )
	{
		printf("error init ");	
		return -1 ;
	}

	pj_caching_pool_init(&cp , NULL , 0 ) ;
	
	pool = pj_pool_create( &cp.factory , NULL , 1024 , 1024 , NULL ) ;
		
	send_buf = (char*)pj_pool_alloc(pool , 200 ) ;

	pj_create_random_string(send_buf , 200 ) ;

	pj_sock_socket( pj_AF_INET() , pj_SOCK_DGRAM() , 0 , &ssock ) ;
	pj_sock_socket( pj_AF_INET() , pj_SOCK_DGRAM() , 0 , &csock ) ;

	pj_bzero(&addr , sizeof(addr) );
	
	pj_str_t  s ;
	addr.sin_family = pj_AF_INET();
	addr.sin_port = pj_htons(34790) ;
	addr.sin_addr = pj_inet_addr(pj_cstr(&s , "127.0.0.1" )) ;
	pj_sock_bind( ssock , &addr , sizeof(addr));
	pj_ioqueue_create(pool , PJ_IOQUEUE_MAX_HANDLES , &ioque ) ;
	pj_ioqueue_register_sock(pool , ioque , ssock , NULL , &test_cb , &ckey ) ;
	
	pj_str_t  tmp ;
	tmp = pj_str("127.0.0.1") ;
	status = pj_sockaddr_in_init(&dst_addr , &tmp , 34780 ) ;
        bytes = 200 ;
	
	do{

		pj_time_val timeout = { 1 , 0 } ;
		status = pj_ioqueue_poll ( ioque , &timeout ) ;
		PJ_LOG(3 , ("this " ,"poll rc = %d" ,status )) ;
		 pj_create_random_string(send_buf , 200 ) ;
		 status  = pj_ioqueue_sendto(ckey , &write_op , send_buf , &bytes , 0 ,&dst_addr ,
                sizeof(dst_addr)) ;
	}while(1) ;		 


	pj_caching_pool_destroy(&cp) ;
	
	pj_shutdown();

	return 0 ;
	


}



你可能感兴趣的:(voip)