PJSIP 支持通过 TCP 传输 SIP 消息,相比 UDP 提供了更可靠的传输机制。以下是关于在 PJSIP 中使用 TCP 的详细指南。
1. 创建 TCP 传输
基本 TCP 传输配置
c
pjsua_transport_config tcp_cfg;
pjsua_transport_config_default(&tcp_cfg);
tcp_cfg.port = 5060; // SIP 标准端口
// 创建 TCP 传输
pjsua_transport_id tcp_id;
pj_status_t status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcp_cfg, &tcp_id);
if (status != PJ_SUCCESS) {
// 错误处理
}
2. TCP 与 UDP 的区别
特性 | TCP | UDP |
---|---|---|
可靠性 | 可靠,有重传机制 | 不可靠,可能丢包 |
连接方式 | 面向连接 | 无连接 |
头部开销 | 较大 (20字节) | 较小 (8字节) |
适用场景 | 不稳定网络环境 | 局域网等稳定环境 |
3. 高级 TCP 配置
保持连接活跃
c
tcp_cfg.qos_type = PJ_QOS_TYPE_VOICE;
tcp_cfg.qos_ignore_error = PJ_TRUE;
// 启用 TCP keepalive
tcp_cfg.tcp_keep_alive = PJ_TRUE;
tcp_cfg.tcp_keep_alive_interval = 30; // 秒
tcp_cfg.tcp_keep_alive_idle = 60; // 秒
设置连接超时
c
tcp_cfg.tcp_conn_timeout = 5000; // 5秒连接超时
4. TCP TLS 配置 (安全传输)
c
pjsua_transport_config tls_cfg;
pjsua_transport_config_default(&tls_cfg);
tls_cfg.port = 5061; // SIP TLS 标准端口
// 配置证书
tls_cfg.tls_setting.ca_list_file = pj_str("/path/to/ca.pem");
tls_cfg.tls_setting.cert_file = pj_str("/path/to/cert.pem");
tls_cfg.tls_setting.privkey_file = pj_str("/path/to/privkey.pem");
// 创建 TLS 传输
pjsua_transport_id tls_id;
status = pjsua_transport_create(PJSIP_TRANSPORT_TLS, &tls_cfg, &tls_id);
5. 多传输配置
可以同时配置 UDP 和 TCP 传输:
c
// 创建 UDP 传输
pjsua_transport_id udp_id;
pjsua_transport_config udp_cfg;
pjsua_transport_config_default(&udp_cfg);
udp_cfg.port = 5060;
pjsua_transport_create(PJSIP_TRANSPORT_UDP, &udp_cfg, &udp_id);
// 创建 TCP 传输
pjsua_transport_id tcp_id;
pjsua_transport_config tcp_cfg;
pjsua_transport_config_default(&tcp_cfg);
tcp_cfg.port = 5060;
pjsua_transport_create(PJSIP_TRANSPORT_TCP, &tcp_cfg, &tcp_id);
6. 强制使用 TCP
如果希望强制使用 TCP 而不是 UDP:
c
pjsua_acc_config acc_cfg;
pjsua_acc_config_default(&acc_cfg);
// 设置首选传输为 TCP
acc_cfg.transport_id = tcp_id;
// 或者通过注册 URI 指定传输
acc_cfg.reg_uri = pj_str("sip:domain.com;transport=tcp");
7. TCP NAT 穿越
TCP 的 NAT 穿越通常比 UDP 简单,但仍需考虑:
c
// 启用 STUN
pjsua_config cfg;
pjsua_config_default(&cfg);
cfg.stun_srv_cnt = 1;
cfg.stun_srv[0] = pj_str("stun.example.com");
// 或使用 ICE
cfg.ice_cfg_use = PJSUA_ICE_CONFIG_USE_CUSTOM;
cfg.ice_cfg.enable_ice = PJ_TRUE;
8. 性能调优
c
// 调整 TCP 缓冲区大小
tcp_cfg.sock_rcvbuf_size = 8192;
tcp_cfg.sock_sndbuf_size = 8192;
// 调整最大连接数
tcp_cfg.tcp_max_connections = 1000;
9. 常见问题解决
连接被拒绝
-
检查防火墙设置
-
确认目标服务器监听 TCP 端口
-
检查网络路由
连接超时
-
增加连接超时时间
-
检查网络延迟
-
验证服务器是否可达
TLS 握手失败
-
确保证书路径正确
-
检查证书有效期
-
验证证书链完整性
10. 调试 TCP 连接
启用详细日志:
c
pjsua_logging_config log_cfg;
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 5; // 更详细的日志
log_cfg.level = 5;
TCP 特定日志可以通过 PJLIB 的 socket 日志查看:
c
extern pj_log_func *pj_log_get_log_func();
pj_log_set_level(3);
pj_log_set_log_func(&my_log_func);
通过合理配置 TCP 传输,可以在不稳定网络环境下获得更可靠的 SIP 通信体验。对于移动设备或穿越复杂网络环境的应用,TCP 通常是更好的选择。