JAIN SIP API详解与GB28181服务器实现

这篇具有很好参考价值的文章主要介绍了JAIN SIP API详解与GB28181服务器实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一 JAIN SIP API

1 摘要

2 关于JAIN SIP API

3 API概述

3.1 maven坐标

3.2 类/接口

3.3 Message接口

3.4 Request接口

3.5 Response接口

4 即时通讯程序

4.1 TextClient代码概述

4.2 Message Processor

4.3 SIP协议栈

4.4 发送SIP请求

4.5 发送会话消息

4.6 接收SIP响应

4.7 接收SIP请求

4.8 处理错误

4.9 小节

二 GB28181SIP服务器——MSH

1 简介

2 GB28181

2.1 注册

2.2 保活

2.2.1 命令流程

2.2.2 协议接口

2.3 MSH代码概述

2.3.1 创建springboot项目

2.3.2 SIP协议栈

2.3.3 接收SIP请求响应

2.3.4 处理SIP请求

2.3.5 发送SIP请求

2.3.6 IPC接入

2.3.7 抓包与流程分析

2.3.7.1 注册

2.3.7.2 保活

3 小结

3.1 SIP服务器

3.2 WEB服务器


一 JAIN SIP API

1 摘要

这篇文章展示了基于Java SE如何创建客户端侧的SIP应用。JAIN SIP API是一个强大的“SIP协议栈”。本文将通过一个简单的即时通讯程序以及一个GB28181协议的简单应用程序,详细的分析该技术。

2 关于JAIN SIP API

Java api for Integrated Networks (JAIN)是一个JCP工作组所管理的电信标准,Session Initiation Protocol(SIP)是一种标准的通信协议,将Java和SIP结合在一起,就得到了JAIN SIP API,这是一个标准的、功能强大的电信API。这个API通常用于客户端应用程序开发。其他基于容器的技术,如SIP Servlet API(参见BEA WebLogic SIP Server的例子),更适合于服务器端开发,但是在GB28181协议应用程序中我们也采用该API用作SIP服务器的开发实现IPC与联网平台的信令交互。

3 API概述

3.1 maven坐标

	<dependency>
    	<groupId>javax.sip</groupId>
   	 	<artifactId>jain-sip-ri</artifactId>
    	<version>1.3.0-91</version>
	</dependency>

3.2 类/接口

下面概述了JAIN SIP API实现中的主要类和接口。

Class / Interface 描述
SipFactory / AddressFactory / HeaderFactory / MessageFactory 工厂类来创建系统的各种对象。它们返回声明了标准接口的对象。
SipStack 您需要的第一个接口,用于创建ListeningPoints和SipProviders。
ListeningPoint 这个接口封装了一个传输/端口对(例如UDP/5060)。
SipProvider 这个接口用来发送SIP消息。您还可以使用此接口为传入的SIP消息注册一个监听器。参见下面的SipListener。
SipListener 您必须实现此接口以允许接收传入的SIP消息。
RequestEvent / ResponseEvent 表示传入的SIP请求、响应。传递给SipListener进行处理。分别包含一个Request或Response对象。
TimeoutEvent 表示传出请求没有回复时的失败条件。传递给SipListener进行处理。
IOExceptionEvent 表示在发送外发请求时出现输入/输出问题时的失败条件。传递给SipListener进行处理。
Request / Response 表示SIP请求、响应。两者都是Message接口的子接口。它们提供对报头、内容和SIP消息的其他部分的访问。
Dialog 此接口的对象封装了一个SIP对话框。(提醒:在对话框中,所有消息都与同一个调用相关;对话通常以INVITE开始,以BYE结束。
ClientTransaction / ServerTransaction 封装SIP事务。(提醒:事务以请求开始,以最终响应结束。事务通常存在于对话框中。)

3.3 Message接口

Message接口是SIP消息的基本接口,下面是可用方法的概述。

Method 描述
void addHeader(Header) void setHeader(Header) 将报头字段设置为SIP消息。第一种方法可用于可重复或具有多个值的标头,如Contact标头。第二个方法删除该类型的现有头,然后添加单个头值。
void removeHeader(Header) 删除此类型的现有标头。
ListIterator getHeaderNames() 返回所有头文件名称。
ListIterator getUnrecognizedHeaders() 返回非标准报头类型的报头名称。
Header getHeader(String) ListIterator getHeaders(String) ListIterator getHeaders(字符串) 特定头的getter。第二种形式返回可重复标头的所有值,或具有多个值的标头,如Contact标头。
void setContent(Object, ContentTypeHeader) 设置消息的有效负载以及Content-Type报头。如果类型是字符串,Content-Length也被设置,否则使用void setContentLength(ContentLengthHeader)。
byte [] getRawContent() Object getContent() 检索消息的有效负载。
void removeContent() 清空有效负载。
void setContentLength(ContentLengthHeader) ContentLengthHeader getContentLength() void setContentLanguage(ContentLanguageHeader) ContentLanguageHeader getContentLanguage() void setContentEncoding(ContentEncodingHeader) ContentEncodingHeader getContentEncoding() void setContentDisposition(ContentDispositionHeader) ContentDispositionHeader getContentDisposition() 与有效负载相关的特殊头访问器。很少使用。
void setExpires(ExpiresHeader) ExpiresHeader getExpires() 管理Expires报头。
void setSipVersion(String) String getSipVersion() 字符串getSipVersion () SIP版本元素的访问器。很少使用,默认为SIP/2.0。
Object clone() 创建消息的副本。很少使用。

3.4 Request接口

Message接口的子接口

Method 描述
String getMethod() void setMethod(String) 方法元素的访问器。可以是任何SIP方法,包括请求接口常量中的方法:ACK、BYE、CANCEL、INVITE、OPTIONS、REGISTER、NOTIFY、SUBSCRIBE、MESSAGE、REFER、INFO、PRACK和UPDATE。
URI getRequestURI() void setRequestURI(URI) 请求URI的访问器,这是SIP请求的第一行。通常,这是SipURI的一个实例。

3.5 Response接口

Message接口的子接口。

Method 描述
void setStatusCode() int getStatusCode() 状态代码的访问器。这可以是任何SIP状态码,包括Response接口的常量成员中的状态码。这里有一些:RINGING (180), OK (200), BAD_REQUEST(400),等等。
void setReasonPhrase(String) String getReasonPhrase() 访问器,用于人类可读的状态代码解释。

4 即时通讯程序

TextClient是一个即时消息传递应用程序,可以通过SIP协议发送和接收文本消息。此应用程序的一个实例可以向另一个实例发送消息,但从理论上讲,此客户机可用于向其他类型的SIP即时消息传递客户机,甚至SIP服务器应用程序发送消息。如下图所示,SIP客户端yrz向另一个SIP客户端yz发送了一条”我是yrz2023年4月18日13:46:22“的消息,随后SIP客户端yz回复了一条”yz收到2023年4月18日13:46:22“的消息。

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

4.1 TextClient代码概述

两个类和一个接口组成了整个TextClient代码。下表介绍:

Class / Interface 描述
TextClient 主类,包含应用程序小部件的Swing窗口。
SipLayer 它负责所有SIP通信。它由TextClient类实例化,并通过MessageProcessor接口回调它。
MessageProcessor 回调接口(观察者模式),用于将SipLayer与其容器解耦。

4.2 Message Processor

创建MessageProcessor接口,将SIP层与GUI层分离。TextClient类实现该接口,其构造函数将SipLayer对象作为参数,您将能够使用SipLayer对象将信息发送回GUI。

public interface MessageProcessor
{
    // 请求回调方法
    void processMessage(String sender, String message);
    // 请求错误回调方法
    void processError(String errorMessage);
    // 响应回调方法
    void processInfo(String infoMessage);
}

4.3 SIP协议栈

让我们开始编写SipLayer类。TextClient必须能够接收来自其他SIP端点的异步消息。这个类实现了SipListener接口来处理传入的消息:

public class SipLayer implements SipListener {
	...
}

SipListener接口方法如下:

public interface SipListener extends EventListener {
    void processRequest(RequestEvent var1);

    void processResponse(ResponseEvent var1);

    void processTimeout(TimeoutEvent var1);

    void processIOException(IOExceptionEvent var1);

    void processTransactionTerminated(TransactionTerminatedEvent var1);

    void processDialogTerminated(DialogTerminatedEvent var1);
}

在本例中,用于处理传入消息的最重要的方法显然是processRequest()和processResponse()。接下来是存储稍后需要的对象的两个字段:username和messageProcessor,这些与SIP API没有直接关系,但是在本例中需要它们。第一个是前面讨论过的MessageProcessor对象,用于回调方法将消息发回给GUI,username用于随时保留用户名,这两个字段有getter和setter方法。

private MessageProcessor messageProcessor;
private String username;

接下来是构造函数,一种启动JAIN SIP API的经典方法——建立一堆以后会有用的对象(工厂和SIP协议栈实例),TextClient就是采用的这种方法。

private SipStack sipStack;
    
private SipFactory sipFactory;
    
private AddressFactory addressFactory;
    
private HeaderFactory headerFactory;
    
private MessageFactory messageFactory;
    
private SipProvider sipProvider;

public SipLayer(String username, String ip, int port) throws	PeerUnavailableException, 
TransportNotSupportedException,InvalidArgumentException, ObjectInUseException, TooManyListenersException {
    
      setUsername(username);
    
      sipFactory = SipFactory.getInstance();
    
      sipFactory.setPathName("gov.nist");
    
      Properties properties = new Properties();
    
      properties.setProperty("javax.sip.STACK_NAME",
    
              "TextClient");
    
      properties.setProperty("javax.sip.IP_ADDRESS",
    
              ip);
    
      sipStack = sipFactory.createSipStack(properties);
    
      headerFactory = sipFactory.createHeaderFactory();
    
      addressFactory = sipFactory.createAddressFactory();
    
      messageFactory = sipFactory.createMessageFactory();
    
      ...

SipFactory用于实例化SipStack实现,但由于可能有多个实现,因此必须通过setPathName()方法命名您想要的那个实现。名称“gov.nist”表示您获得的SIP堆栈。

SipStack对象具有许多属性。至少,您必须设置堆栈名称。所有其他属性都是可选的。在这里,我设置了一个由堆栈使用的IP地址,用于一台计算机有多个IP地址的情况。注意,这里有标准属性(所有SIP API实现都必须支持)和非标准属性(依赖于实现)。

下一步是创建一对ListeningPoint和SipProvider对象。这些对象提供了发送和接收消息的通信功能。TCP有一组,UDP有一组。这也是你选择SipLayer作为传入SIP消息的监听器的地方:

...
    
      ListeningPoint tcp = sipStack.createListeningPoint(port, "tcp");
    
      ListeningPoint udp = sipStack.createListeningPoint(port, "udp");
    
      sipProvider = sipStack.createSipProvider(tcp);
    
      sipProvider.addSipListener(this);
    
      sipProvider = sipStack.createSipProvider(udp);
    
      sipProvider.addSipListener(this);
    
    }

构造函数就是这样结束的。您已经使用JAIN SIP API创建了一个SipStack实例、一堆工厂、两个listeningpoint和一个SipProvider。这些对象将在接下来的方法中用于发送和接收消息。

4.4 发送SIP请求

现在让我们编写一个使用JAIN SIP API发送SIP消息的方法,在此之前你必须非常了解SIP协议。SIP API是相当低级的抽象,在大多数情况下,不使用默认值或隐藏头、请求uri或SIP消息的内容。这种设计的优点是您可以完全控制SIP消息所包含的内容。

发送一个SIP请求大致分为四个部分:

  • 创建主要元素

  • 创建消息

  • 完整的消息

  • 发送消息

使用JAIN SIP API构造消息最少需要以下主要SIP元素:

  • 请求URI

  • 方法

  • 通话身份头

  • CSeq头

  • 从标题

  • Via报头数组

  • Max-forwards头

下面的代码片段创建了所有这些元素:

public void sendMessage(String to, String message) throws
                ParseException, InvalidArgumentException, SipException {
    
            SipURI from = addressFactory.createSipURI(getUsername(),
                    getHost() + ":" + getPort());
        Address fromNameAddress = addressFactory.createAddress(from);
            fromNameAddress.setDisplayName(getUsername());
            FromHeader fromHeader =
                    headerFactory.createFromHeader(fromNameAddress,
                            "textclientv1.0");
    
            String username = to.substring(to.indexOf(":")+1, to.indexOf("@"));
            String address = to.substring(to.indexOf("@")+1);
    
            SipURI toAddress =
                    addressFactory.createSipURI(username, address);
            Address toNameAddress = addressFactory.createAddress(toAddress);
            toNameAddress.setDisplayName(username);
            ToHeader toHeader =
                    headerFactory.createToHeader(toNameAddress, null);
    
            SipURI requestURI =
                    addressFactory.createSipURI(username, address);
            requestURI.setTransportParam("udp");
    
            ArrayList viaHeaders = new ArrayList();
            ViaHeader viaHeader =
                    headerFactory.createViaHeader(
                            getHost(),
                            getPort(),
                            "udp",
                            null);
            viaHeaders.add(viaHeader);
    
            CallIdHeader callIdHeader = sipProvider.getNewCallId();
    
            CSeqHeader cSeqHeader =
                    headerFactory.createCSeqHeader(1, Request.MESSAGE);
    
            MaxForwardsHeader maxForwards =
                    headerFactory.createMaxForwardsHeader(70);
            ...

我使用在构造函数HeaderFactory和AddressFactory中创建的工厂来实例化这些元素。接下来让我们实例化实际的SIP消息本身,传入之前创建的所有元素:

Request request =  messageFactory.createRequest(
            requestURI, Request.MESSAGE, callIdHeader, cSeqHeader,
            fromHeader, toHeader, viaHeaders,       maxForwards);
    ...

注意,这一步使用了MessageFactory。然后,让我们向消息添加其他元素:联系人标头和消息的内容(有效负载),也可以添加自定义标题。

SipURI contactURI = addressFactory.createSipURI(getUsername(),
                    getHost());
            contactURI.setPort(getPort());
            Address contactAddress = addressFactory.createAddress(contactURI);
            contactAddress.setDisplayName(getUsername());
            ContactHeader contactHeader =
                    headerFactory.createContactHeader(contactAddress);
            request.addHeader(contactHeader);
            ContentTypeHeader contentTypeHeader =
                    headerFactory.createContentTypeHeader("text", "plain");
            request.setContent(message, contentTypeHeader);
            ...

最后,使用SipProvider实例发送消息:

sipProvider.sendRequest(request);    }

4.5 发送会话消息

你在会话外发送我们的信息,这意味着消息之间没有关联,这对于TextClient这样的简单即时消息传递应用程序来说效果很好。另一种方法是使用INVITE消息创建一个会话,然后在该会话内发送消息。TextClient不使用这种技术,但是是值得学习的东西,本小节描述了如何做到这一点。

在会话中发送消息需要创建Dialog和Transaction对象。在初始消息(即创建会话的消息)上,不使用提供程序发送消息,而是实例化一个Transaction,然后从中获取Dialog。您保留Dialog引用以供以后使用。然后使用事务发送消息:

ClientTransaction trans = sipProvider.getNewClientTransaction(invite);
    dialog = trans.getDialog();
    trans.sendRequest();

稍后,当您希望在同一个会话中发送新消息时,您可以使用前面的Dialog对象来创建一个新请求。然后,您可以对请求进行消息处理,最后,使用Transaction发送消息。

request = dialog.createRequest(Request.MESSAGE);
    request.setHeader(contactHeader);
    request.setContent(message, contentTypeHeader);
  
    ClientTransaction trans = sipProvider.getNewClientTransaction(request);
    trans.sendRequest();

从本质上讲,在现有会话中发送消息时,您跳过了“创建主要元素”步骤。当您使用INVITE创建对话框时,不要忘记在对话框结束时发送一个BYE消息来清理它。此技术还用于刷新注册和订阅。

在前面,您已经看到了SipListener接口,其中包含processDialogTerminated()和processTransactionTerminated()方法。它们分别在对话框和事务结束时自动调用。通常,实现这些方法是为了清理(例如,丢弃Dialog和Transaction实例)。您将把这两个方法留空,因为在TextClient中不需要它们。

4.6 接收SIP响应

前面,您注册了传入消息的监听器。监听器接口SipListener包含方法processResponse(),当SIP响应消息到达时,由SIP协议栈调用该方法。processResponse()接受一个ResponseEvent类型的参数,它封装了一个Response对象。

public void processResponse(ResponseEvent evt) {         
	Response response = evt.getResponse();         
	int status = response.getStatusCode();          
	if( (status >= 200) && (status < 300) ) { //Success!                 
	messageProcessor.processInfo("--Sent");                 
	return;         
	}
    messageProcessor.processError("Previous message not sent: " + status); 
}

在此方法中,您将检查先前MESSAGE消息的响应是否表示成功(2xx范围的状态码)或错误(否则)。然后通过回调接口将此信息转发给用户。

通常,您只读取processResponse()方法中的Response对象。唯一的例外是对INVITE消息的成功响应;在这种情况下,你必须发送一个ACK请求,就像这样:

Dialog dialog = evt.getClientTransaction().getDialog();
Request ack =  dialog.createAck();
dialog.sendAck(ack);

4.7 接收SIP请求

接收SIP请求消息与接收响应一样简单。您只需实现SipListener接口的另一个方法processRequest(), SIP堆栈将自动调用它。该方法的唯一参数是RequestEvent对象,其中包含Request对象。这是你之前见过的相同类型,它有相同的方法。但是,您不应该在传入请求上设置任何字段,因为这没有多大意义。

processRequest()的典型实现就是分析请求,然后创建并发回适当的响应:

public void processRequest(RequestEvent evt) {         
	Request req = evt.getRequest();          
	String method = req.getMethod();         
	if( ! method.equals("MESSAGE")) { //bad request type.                 
		messageProcessor.processError("Bad request type: " + method);                 
		return;         
	}          
	FromHeader from = (FromHeader)req.getHeader("From");         
	messageProcessor.processMessage(from.getAddress().toString(), new String(req.getRawContent()));         	Response response=null;         
	try { //Reply with OK
		response = messageFactory.createResponse(200, req);                 
		ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME);                 
		toHeader.setTag("888"); //Identifier, specific to your application                 
		ServerTransaction st = sipProvider.getNewServerTransaction(req);           				
		st.sendResponse(response);	
	} catch (Throwable e) {                 
		e.printStackTrace();                 
		messageProcessor.processError("Can't send OK reply.");         
	} 
}

在这种情况下,您总是用一个成功响应(200)来回复,但是您也可以发回任何错误响应(通常是4xx范围)。

4.8 处理错误

SipListener接口中还有其他尚未实现的方法。当由于特定原因无法发送请求时,由SIP协议调用它们。例如,当接收消息的端点没有及时应答时,将调用processTimeout()。这是一种没有响应的特殊情况,因此没有可用的response对象。TimeoutEvent参数包含超时请求的ClientTransaction,如果需要,可以使用该参数链接回原始请求。在这个实现中,你只需使用回调接口通知用户:

public void processTimeout(TimeoutEvent evt) {         
	messageProcessor.processError("Previous message not sent: " + "timeout"); 
}

类似地,Input/Output (IO)错误的处理方法如下:

public void processIOException(IOExceptionEvent evt) {         
	messageProcessor.processError("Previous message not sent: " + "I/O Exception"); 
}

4.9 小节

本文概述了JAIN SIP API,并展示了如何编写一个简单的应用程序来使用这项技术。现在,您应该对可用的api有了很好的了解,并且知道如何使用SIP编写自己的IM客户机。

以上内容主要来自ORACLE官网《An Introduction to the JAIN SIP API》文章,TextClient源码下载地址也在文章提供,感兴趣的同学可以阅读原文,文章地址:An Introduction to the JAIN SIP API。

下面将该API应用到安防领域实现一个能够满足GB28181协议的SIP服务器。

二 GB28181SIP服务器——MSH

1 简介

SIP(Session Initiation Protocol,会话发起协议)是一种基于文本的网络通信协议,主要用于实现语音、视频和数据等多种媒体资源的实时传输。SIP信令在以下应用领域和行业中发挥着重要作用:
1.语音通信:SIP协议可用于固定电话、移动电话和网络电话之间的通话,实现电话拨号、通话建立、通话保持和通话结束等功能。
2.视频通信:通过SIP协议,用户可以实现音视频通话、视频会议和协同工作等应用,满足企业和个人之间的沟通需求。
3.即时通讯:SIP协议可应用于即时通讯领域,提供文本、图片、语音和视频等丰富的通信方式,如微信、WhatsApp等。
4.网络电视和多媒体广播:SIP协议可用于实现点播、直播和时移电视等多媒体服务,满足用户对多媒体内容的需求。
5.智能家居:通过SIP协议,可以实现家庭设备之间的互联互通,如智能音响、智能摄像头、智能照明等,提升家居生活的便捷性和舒适度。
6.企业通信:SIP协议可应用于企业内部通信系统,实现电话交换、电话会议、呼叫中心等功能,提高企业通信效率。
7.物联网:SIP协议可用于物联网设备之间的通信,实现智能控制、远程监控和数据分析等应用。
公共服务:SIP协议在公共安全、紧急救援、交通管理等领域具有广泛应用,提高公共服务的质量和效率。
8.教育:SIP协议可以实现远程教学、在线课堂和视频讲座等功能,拓展教育领域的发展空间。
9.医疗:通过SIP协议,可以实现远程诊断、视频咨询和在线挂号等医疗服务,提高医疗资源的利用效率。

本demo(项目)是JAIN SIP API的应用,适用于安防领域,当然如果你是一位其他领域的从业者,该项目代码也会起到举一反三、抛砖引玉的作用。

本项目不仅仅包含了SIP服务器,还有流媒体服务器和WEB服务器的实现,是一个完整的程序,方便实现二次开发与功能拓展。下文仅仅对SIP服务器的实现做简单的介绍。

2 GB28181

在GB28181-2022协议规范中“9控制、传输流程和协议接口”中规定了IPC注册、注销、点播、状态信息报送等控制的命令流程与协议接口,下面我们将按照GB28181流程,采用JAIN SIP API实现IPC的向SIP服务器的注册与状态信息报送(保活)。

2.1 注册

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

2.2 保活

2.2.1 命令流程

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

2.2.2 协议接口

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

2.3 MSH代码概述

2.3.1 创建springboot项目

创建一个springboot项目并引入JAIN SIP API依赖。

2.3.2 SIP协议栈

创建SipLayer声明CommandLineRunner接口,项目启动时会建立一堆以后会有用的对象:SipFactory、SipStack、ListeningPoint,同时创建TCP与UDP监听器用来兼容IPC的TCP/UDP接入。

SipLayer类注入SipConfig对象,该对象配置了SIP服务器的ip、端口、域名、id和密码。

SipLayer类注入SipServerListener,SipServerListener接口继承于SipListener,SipServerListener的子类为SipServerListenerImpl,SipServerListenerImpl为实现SIP请求响应的处理。

2.3.3 接收SIP请求响应

SipServerListenerImpl类实现了SipListener接口,重写processRequest()与processResponse()方法,来接收SIP请求与响应。该类采用了类似观察者模式的设计思路,声明了两个线程安全的容器reqHandlerMap与respHandlerMap用来存放不同的SIP请求响应的真实处理对象,例如processRequest()接收到一个REGISTER请求,利用java继承与多态的特性,processRequest()方法根据SIP方法类型为key获取到真实处理对象,最后由真实处理对象处理REGISTER请求。

在真实的平台与IPC进行信令交互时,会面临并发处理多种SIP请求响应的场景,所以在processRequest()与processResponse()方法上使用@Aync()注解,实现异步处理SIP信令。

2.3.4 处理SIP请求

SipReqHandler接口的实现类有两个RegisterReqHandler和KeepaliveReqHandler,分别实现IPC的注册与保活,代码实现流程请参照该小节的命令流程部分,最后我们将进行抓包分析整个信令的交互流程。

我们发现GB28181中,有很多控制传输流程都是通过MESSAGE方法+MANSCDP命令集实现的,所以我们要在接收到IPC的MESSAGE方法时,解析MANSCDP命令集,解析到cmdType = "Keepalive"的请求,才是保活请求,然后回复给IPC200,其他的MESSAGE请求这里暂时不处理。

2.3.5 发送SIP请求

SipSender类实现了SIP消息报文的封装,通过sendResponse()方法回复IPC消息。

2.3.6 IPC接入

1.首先启动SIP服务器,查看SIP服务器的配置信息:

#SIP
# SIP服务器IP
sip.ip=10.192.33.34
# SIP服务监听的端口
sip.port=5060
# SIP域
sip.domain=34020000
# SIP服务器国标ID
sip.id=34020000001320000010
# SIP服务器密码
sip.password=admin123

2.IPC平台接入配置需要配置SIP服务器信息: JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

 IPC平台接入的密码为SIP服务器密码,用于服务器校验,校验正确才能实现IPC的注册。IPC每间隔60秒发送一次心跳信息,观察SIP服务器日志,满足GB28181规定命令流程,下面抓包分析信令交互流程。

3.SIP服务器日志:

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

 JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

 JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

2.3.7 抓包与流程分析
2.3.7.1 注册

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

REGISTER sip:34020000001320000010@34020000 SIP/2.0
Via: SIP/2.0/UDP 10.192.33.95:5060;rport;branch=z9hG4bK863117711
From: <sip:34020000001320000002@34020000>;tag=294565749
To: <sip:34020000001320000002@34020000>
Call-ID: 1973051184
CSeq: 1 REGISTER
Contact: <sip:34020000001320000002@10.192.33.95:5060>
Max-Forwards: 70
User-Agent: IP Camera
Expires: 3600
Content-Length: 0

SIP/2.0 401 Unauthorized
CSeq: 1 REGISTER
Call-ID: 1973051184
From: <sip:34020000001320000002@34020000>;tag=294565749
To: <sip:34020000001320000002@34020000>
Via: SIP/2.0/UDP 10.192.33.95:5060;rport=5060;branch=z9hG4bK863117711;received=10.192.33.95
WWW-Authenticate: Digest realm="34020000",qop="auth",nonce="1ba00522b15b098aa2c05150cdb0df31",algorithm=MD5
User-Agent: sip-server-yrz
Content-Length: 0

REGISTER sip:34020000001320000010@34020000 SIP/2.0
Via: SIP/2.0/UDP 10.192.33.95:5060;rport;branch=z9hG4bK713030866
From: <sip:34020000001320000002@34020000>;tag=294565749
To: <sip:34020000001320000002@34020000>
Call-ID: 1973051184
CSeq: 2 REGISTER
Contact: <sip:34020000001320000002@10.192.33.95:5060>
Authorization: Digest username="34020000001320000002", realm="34020000", nonce="1ba00522b15b098aa2c05150cdb0df31", uri="sip:34020000001320000010@34020000", response="ff34c4434d132ad9b956c729aa229194", algorithm=MD5, cnonce="0a4f113b", qop=auth, nc=00000001
Max-Forwards: 70
User-Agent: IP Camera
Expires: 3600
Content-Length: 0

SIP/2.0 200 OK
CSeq: 2 REGISTER
Call-ID: 1973051184
From: <sip:34020000001320000002@34020000>;tag=294565749
To: <sip:34020000001320000002@34020000>
Via: SIP/2.0/UDP 10.192.33.95:5060;rport=5060;branch=z9hG4bK713030866;received=10.192.33.95
Date: 2023-04-19T11:29:33.703
Contact: <sip:34020000001320000002@10.192.33.95:5060>
Expires: 3600
User-Agent: sip-server-yrz
Content-Length: 0
  1. IPC发起REGISTER请求,未携带Authorization认证信息。

  2. SIP服务器回复401与认证加密算法。

  3. IPC重新发起REGISTER并携带Authorization认证信息。

  4. SIP服务器认证成功后回复200,IPC注册成功。

2.3.7.2 保活

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

MESSAGE sip:34020000001320000010@34020000 SIP/2.0
Via: SIP/2.0/UDP 10.192.33.95:5060;rport;branch=z9hG4bK1171736073
From: <sip:34020000001320000002@34020000>;tag=699092543
To: <sip:34020000001320000010@34020000>
Call-ID: 776784695
CSeq: 20 MESSAGE
Content-Type: Application/MANSCDP+xml
Max-Forwards: 70
User-Agent: IP Camera
Content-Length:   182

<?xml version="1.0" encoding="GB2312"?>
<Notify>
<CmdType>Keepalive</CmdType>
<SN>3634867</SN>
<DeviceID>34020000001320000002</DeviceID>
<Status>OK</Status>
<Info>
</Info>
</Notify>
SIP/2.0 200 OK
CSeq: 20 MESSAGE
Call-ID: 776784695
From: <sip:34020000001320000002@34020000>;tag=699092543
To: <sip:34020000001320000010@34020000>;tag=1681876509157
Via: SIP/2.0/UDP 10.192.33.95:5060;rport=5060;branch=z9hG4bK1171736073;received=10.192.33.95
User-Agent: sip-server-yrz
Content-Length: 0
  1. IPC发起MESSAGE请求并携带设备ID。

  2. SIP服务器回复200。

3 小结

3.1 SIP服务器

目前实现的为注册、保活、设备信息查询、目录查询、点播。下图为VLC播放取流播放截图。

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

3.2 WEB服务器

目前实现点播、通道同步、flv/hls/webrtc(zlm和webrtc-streame两种流媒体)格式流web预览。

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频

支持人脸识别,人脸识别部分请查看文章

代码持续更新中...

需要SIP服务器源码请私信我^-^

JAIN SIP API详解与GB28181服务器实现,后端服务开发,java,音视频文章来源地址https://www.toymoban.com/news/detail-698381.html

到了这里,关于JAIN SIP API详解与GB28181服务器实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • GB28181国标平台测试软件NTV-GBC(包含服务器和模拟客户端)

    GB28181国标平台测试软件NTV-GBC用于对GB28181国标平台进行测试(测试用例需要服务器软件,服务器软件可以是任何标准的国标平台,我们测试使用的是NTV-GBS),软件实现了设备注册、注销、目录查询,消息订阅、INVITE,BYE、KEEPLIVE、OPTION信令。本文档介绍的模拟软件的使用方法。

    2024年02月11日
    浏览(14)
  • GB28181协议--SIP协议介绍

      SIP(Session Initiation Protocol,会话初始协议)是一个用于建立、更改和终止多媒体会话的应用层控制协议,其中的会话可以是IP电话、多媒体会话或多媒体会议(GB28181安防使用的是SIP协议)。SIP是IETF多媒体数据和控制体系结构的核心协议。其主要目的是为了解决IP网中的信

    2023年04月23日
    浏览(23)
  • asterisk配置实现sip服务器,进行sip视频通话

    1.下载asterisk 2.配置sip.conf文件 sip.conf文件的目录默认在/etc/asterisk/下,修改之前最好备份一下,在/etc/目录下执行: 在sip.conf文件中修改: 文件最后添加用户: 中间省略了无需修改的内容。 2.配置extensions.conf文件 在extensions.conf文件中修改为: 3.启动asterisk 执行以下命令: 1

    2024年01月23日
    浏览(28)
  • window下搭建WVP+ZLMediaKit服务实现获取GB28181视频(一、WVP服务搭建)

    前段时间因为公司要求,客户需要整合各种摄像机,提出需要使用国标GB28181协议,于是查了各种资料和视频,总算将服务搭建下来了。后续可能还需要整一个linux版的。趁着现在还记得,先将整合的流程记录一下 官方文档:WVP-PRO文档 在官方文档有详细的说明,但是也有一些

    2024年01月20日
    浏览(25)
  • 阿里云服务器安装asterisk开源sip软交换服务器

    阿里云服务器安装asterisk开源sip软交换服务器 1、使用./contrib/scripts/install_prereq install自动安装依赖环境,此处是重要步骤。 2、版本的问题 centos版本:CentOS Linux release 7.5.1804 (Core) asterisk版本:16.0.0 当5060不能监听的时候更换版本 3、启动后的报错不需要理会,非必要模块会拒绝

    2024年02月06日
    浏览(29)
  • Sip - Ubuntu 配置 miniSIPServer 服务器(测试用)

    客户提供的账号过期了,简单搭建 SIP 服务器,以便测试使用。个人认为这个配置起来最为简单,且测试功能足够。 官网miniSIPServer - 基于 Windows 以及 Linux 平台的 VoIP (SIP) 服务器软件. miniSIPServer 可能是最容易使用的 VoIP(SIP) 服务器软件,VoIP 领域专家可以轻松部署丰富的企业通

    2024年02月02日
    浏览(22)
  • WebRTC+Kamamilio+rtpengine+Websocket SIP服务器搭建教程

    发现国内使用SIP的资料真的很少,由于公司需要使用语音视频电话,在网上找了一大圈也没找到相关案例,最后自己折腾出一个方案,故此分享出来。 开始之前不得不介绍一下这五个东西。 Kamamilio 是 OpenSER 的前身,是C语言写的一个Sip服务,支持在 在Linux/UNIX系统上运行,优

    2024年02月15日
    浏览(48)
  • window下搭建WVP+ZLMediaKit服务实现获取GB28181视频(三、WVP+ZLMediaKit服务启动,并连接摄像头)

    前面两篇文章分别介绍了WVP服务和ZLMediaKit服务的搭建,现在介绍这两个服务如何达到通讯效果 配置通讯的mediaServerId和media.id 1、在ZLMediaKit服务第一次启动后,会出现config.ini文件,这个文件在服务没有启动之前是不存在的,打开这个配置文件,在里面找到mediaServerId  2、打开

    2024年02月08日
    浏览(25)
  • 【GB28181】协议详解

    GB28181协议指的是国家标准GB/T 28181—2016《公共安全视频监控联网系统信息传输、交换、控制技术要求》。 该标准规定了公共安全视频监控联网系统的互联结构, 传输、交换、控制的基本要求和安全性要求, 以及控制、传输流程和协议接口等技术要求,是视频监控领域的国家

    2024年02月11日
    浏览(14)
  • HappyGBS GB28181信令服务 - 开篇

    HappyGBS GB28181信令服务 - 开篇 HappyGBS GB28181信令服务 - 运行 HappyGBS GB28181信令服务 - 文档 HappyGBS设计理念:大道至简,精益求精 HappyGBS服务,包含 信令服务(HappyCMS) 和 流媒体服务(ZLMediaKit) 两部分 HappyCMS 提供功能 1.  自动监听SIP协议端口,当有设备注册时,会记录该设备信息,

    2023年04月08日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包