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 ;
}