PyVoIP客户端未响应SIP服务器OPTIONS消息,呼叫异常如何解决?
解决pyVoIP客户端不响应OPTIONS请求导致来电丢失的问题
问题分析
SIP服务器发送OPTIONS请求是心跳检测机制,若客户端未返回200 OK响应,服务器会判定客户端离线,停止转发来电。pyVoIP库默认没有处理OPTIONS请求的逻辑,这就是来电时有时无的核心原因。
解决方案
通过继承VoIPPhone类并重写handle_request方法,手动处理OPTIONS请求并返回200 OK响应。同时修复原代码中的文件写入bug,优化循环逻辑。
修改后的完整代码
from pyVoIP.VoIP import VoIPPhone, CallState, PhoneStatus, InvalidStateError from pyVoIP.SIP import SIPRequest, SIPResponse import time import datetime class CustomVoIPPhone(VoIPPhone): def handle_request(self, request): # 处理OPTIONS请求,返回200 OK if request.method == "OPTIONS": response = SIPResponse(200, "OK", request) self.sip.send(response) return # 其他请求交给父类处理 super().handle_request(request) def answer(call): try: print(call.state) anum = call.request.headers["From"]["number"] # 构造日志行 log_line = f',{datetime.datetime.now().strftime("%Y%m%d")}, {datetime.datetime.now().strftime("%X")}, {datetime.datetime.now().strftime("%f")},,,,,,,{anum},0662279775,,,' print(log_line) # 追加写入日志文件(修复原代码未赋值文件对象的bug) with open('tmp.csv', 'a+', encoding='utf-8') as f: f.write(log_line + '\n') print(anum) call.answer() call.hangup() except InvalidStateError as e: print(e) pass if __name__ == "__main__": # 使用自定义的电话类 vp = CustomVoIPPhone('79.98.45.133', 5060, '06xxxxx', 'xxxxxxxx', callCallback=answer) print(f'VOIP PHONE INITIALIZED: status = {vp._status}') vp.start() print(f'VoIP PHONE STARTED: status = {vp._status}') # 等待注册完成,添加sleep避免CPU空转 while vp._status in (PhoneStatus.REGISTERING, PhoneStatus.INACTIVE): time.sleep(0.1) print(f'WHILE LOOP STATUS ENDED: status = {vp._status}') input('Press ENTER to stop') time.sleep(5) vp.stop() print(f'STOPPED VOIP PHONE: status = {vp._status}') time.sleep(5)
关键修改说明
- OPTIONS请求处理:自定义
CustomVoIPPhone类,重写handle_request方法,识别OPTIONS请求后立即返回200 OK响应,让服务器确认客户端在线。 - 文件写入修复:原代码中
open后未将文件对象赋值给f,导致f.write报错;改用with语句自动管理文件,并使用a+模式追加日志(避免每次清空文件)。 - 循环优化:等待注册状态时添加
time.sleep(0.1),降低CPU占用。
内容的提问来源于stack exchange,提问作者Giorgio Torassa
相关产品推荐
相关产品推荐

