当前位置: 首页 > 工具软件 > JAIN-SIP > 使用案例 >

Java 用JainSip实现服务器端SIP通讯----之监听篇

仲孙才捷
2023-12-01

Java web服务器实现SIP通讯(或GB28181),一般有两种选择:SipServlet和JainSip

前者更适合服务器,后者较适合客户端

前者用类似web servlet的方式实现了sip通信,直接就实现了多线程的sip通信的并发

后者相对底层一点,不具有并发能力

但,前者需要Web容器的支持,目前好象能用的只有两三种,且与web servlet并存性好像也不好

故,考虑到要用tomcat容器,所以用JainSip实现具有sip通信能力的web服务器

 

1. 设计思路

JainSip实现,主要是面向SipListener监听接口编程

此监听接口一个项目中只能有一个实现,但可以同时对多个端口进行监听

一个监听端口对应一个ListeningPoint监听对象,并由一个SipProvider对象管理

此接口要实现6个处理方法:

public void processRequest(RequestEvent evt)

public void processResponse(ResponseEvent evt)

public void processTimeout(TimeoutEvent evt)

public void processTransactionTerminated(TransactionTerminatedEvent evt)

public void processDialogTerminated(DialogTerminatedEvent evt)

public void processIOException(IOExceptionEvent evt)

这些方法是串行处理的,要用多线程实现并行处理

前两个是接收消息,发送sip消息要用对应端口的SipProvider对象来发送

 

2. 监听的建立

建立实现SipListener接口的基类:

public abstract class Siplistener implements SipListener

构造函数中设置sip工厂类参数:

sipFactory = SipFactory.getInstance();

sipFactory.setPathName("gov.nist");

 

用一个方法创建监听:

public void createListenPoint(String listenerName, String serverName, String ip, int port)

//创建SipStack

Properties properties = new Properties();

properties.setProperty("javax.sip.STACK_NAME", serverName);

properties.setProperty("javax.sip.IP_ADDRESS", ip);

properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", 32);

properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "textclient.txt");

properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "textclientdebug.log");

SipStack sipStack = sipFactory.createSipStack(proerties);

 

//udp 创建SipProvider

SipProvider sipProvider;

ListeningPoint udp = sipStack.createListeningPoint(ip, port, "udp");

sipProvider = sipStack.createSipProvider(udp);

//保存SipProvider对象

String strHashcode = Integer.toHexString(sipProvider.hashCode());

sipProviderMap.put(strHashcode, sipProvider);

sipProviderNameMap.put(listenerName+"/udp", strHashcode);

sipProviderNameMap.put(strHashcode, listenerName+"/udp");

sipProvider.addSipListener(this);

 

//tcp 创建SipProvider

ListeningPoint tcp = sipStack.createListeningPoint(ip, port, "tcp");

sipProvider = sipStack.createSipProvider(tcp);

//保存SipProvider对象

String strHashcode = Integer.toHexString(sipProvider.hashCode());

sipProviderMap.put(strHashcode, sipProvider);

sipProviderNameMap.put(listenerName+"/tcp", strHashcode);

sipProviderNameMap.put(strHashcode, listenerName+"/tcp");

sipProvider.addSipListener(this);

 

可以建立多个端口的tcp/udp监听,需根据监听名和传输类型方便取出各自的SipProvider

 

3. 处理线程

建立请求处理线程:

public abstract class SipProcessReqThread implements Runnable {

protected Siplistener siplistener;

protected Request req;

protected RequestEvent evt;

protected SipProvider sipProvider;

protected String listenerName;

 

public void run() {

  if(null!=req){

    onProcess();

  }

}

protected abstract void onProcess();

 

public void setParam(Siplistener siplistener,  Request req, RequestEvent evt, SipProvider sipProvider, String listenerName) {

  this.siplistener=siplistener;

  this.req=req;

  this.evt=evt;

  this.sipProvider=sipProvider;

  this.listenerName=listenerName;

}

}

 

超时处理线程:

public abstract class SipDialogTimeout implements Runnable {

protected TimeoutEvent evt;

protected Dialog dialog;

protected boolean isReturn;

 

public void run() {

  if(evt.isServerTransaction()){

    ServerTransation serverTransation = evt.getServerTransation();

    if(serverTransation!=null){

      dialog=serverTransation.getDialog();

    }

    isReturn = true;

  }else{

    ClientTransation clientTransation = evt.getClientTransation();

    if(clientTransation!=null){

      dialog=clientTransation.getDialog();

    }

    isReturn = true;

  }

  if(null!=dialog){

    onProcess(isReturn);

  }

}

protected abstract void onProcess(boolean isReturn);

 

public void setParam(TimeoutEvent evt) {

  this.evt=evt;

}

}

 

其它处理线程与上面的类似

 

4. 处理方法

接收请求的处理:

public void processRequest(RequestEvent evt) {

  Request req = evt.getRequest();

  String str=evt.getSource().toString();

  str=str.substring(str.indexOf('@')+1);

  SipProvider sipProvider=sipProviderMap.get(str);

  String strHashcode=Integer.toHexString(sipProvider.hashCode());

  String strListenerName=sipListenerNameMap.get(strHashcode);

  SipProcessReqThread sipProcessReqThread=new_SipProcessReqThread();

  sipProcessReqThread.setParam(this, req, evt, sipProvider, strListenerName);

  startThread(sipProcessReqThread);

}

 

超时处理:

public void processTimeout(TimeoutEvent evt) {

  SipDialogTimeout sipDialogTimeout=new_SipDialogTimeout();

  sipDialogTimeout.setParam(evt);

  startThread(sipDialogTimeout);

}

 

其它处理与之类似

 

启动Runnable线程的共用方法:

private void startThread(Runnable runnable) {

  Thread thread=new Thread(runnable);

  try{

    thread.start();

  }catch(Exception e){

  }

}

 

5. 发送请求

public boolean sendRequest(String name, String type, Request req) {

  SipProvider sipProvider=getProvider(name,type);

  if(sipProvider==null){

    return false;

  }

  try{

    sipProvider.sendRequest(req);

  }catch(SipException e){

    return false;

  }

  return true;

}

 

6. 处理对象的注入

用方法

public abstract SipDialogTimeout new_SipDialogTimeout();

public abstract SipProcessReqThread new_ProcessReqThread();

public abstract SipProcessRespThread new_ProcessRespThread();

子类实现后,注入新对象

 

7. Jar包

concurrent.jar

JainSipApi1.2.jar

JainSipRi1.2.jar

log4j-1.2.8.jar

 

 类似资料: