gb28181简单实现sip信令服务器(java版基于springboot):一、netty创建udp服务器

以下仅代表个人理解,仅供参考,欢迎大佬纠正!!!

maven依赖

<!-- springboot配置依赖 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<optional>true</optional>
</dependency>
<!-- netty -->
<dependency>
	<groupId>io.netty</groupId>
	<artifactId>netty-all</artifactId>
	<version>4.1.38.Final</version>
</dependency>

SipUdpServer 服务类

import com.fengyulei.fylsipserver.config.ConfigInfo;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
//整合springboot 直接单例注入
@Component
public class SipUdpServer implements Runnable{

    private static final Logger logger = LoggerFactory.getLogger(SipUdpServer.class);
	//配置类注入
    @Autowired
    private ConfigInfo configInfo;
	//udp服务器可以使用单例Handler,方便其他类注入
    @Autowired
    private SipServerHandler sipServerHandler;

    @PostConstruct
    private void init(){
        //异步启动netty 不使用异步会阻塞程序
        Thread thread=new Thread(this);
        thread.setDaemon(true);
        thread.setName("sip server netty thread");
        thread.start();
    }

    @Override
    public void run(){
        EventLoopGroup bossGroup=new NioEventLoopGroup();
        try{
            //通过NioDatagramChannel创建Channel,并设置Socket参数支持广播
            //UDP相对于TCP不需要在客户端和服务端建立实际的连接,因此不需要为连接(ChannelPipeline)设置handler
            Bootstrap b=new Bootstrap();
            b.group(bossGroup)
                    .channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST, true)
                    .handler(sipServerHandler);
            ChannelFuture channelFuture=b.bind(configInfo.getServerPort()).sync();
            sipServerHandler.setChannelFuture(channelFuture);
            logger.info("SipUdpServer 启动成功 ip:[{}],port:[{}]",configInfo.getServerIp(),configInfo.getServerPort());
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            logger.error(e.getMessage(),e);
        }finally{
            bossGroup.shutdownGracefully();
        }
    }



}

ConfigInfo 配置类

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.NotEmpty;

@Validated
@Component
@ConfigurationProperties(prefix = "fyl.sip")
public class ConfigInfo {

    @NotEmpty(message = "serverId 不能为空")
    private String serverId;

    private Integer serverPort=5060;

    private String serverIp="0.0.0.0";

    @NotEmpty(message = "mediaServerIp 不能为空")
    private String mediaServerIp;

    @NotEmpty(message = "mediaServerPort 不能为空")
    private String mediaServerPort;


    @NotEmpty(message = "sipDeviceKey 不能为空")
    private String sipDeviceKey;

    private Integer mediaUdpTcpServerPort;

    public Integer getMediaUdpTcpServerPort() {
        return mediaUdpTcpServerPort;
    }

    public void setMediaUdpTcpServerPort(Integer mediaUdpTcpServerPort) {
        this.mediaUdpTcpServerPort = mediaUdpTcpServerPort;
    }

    public String getSipDeviceKey() {
        return sipDeviceKey;
    }

    public void setSipDeviceKey(String sipDeviceKey) {
        this.sipDeviceKey = sipDeviceKey;
    }

    public String getServerId() {
        return serverId;
    }

    public void setServerId(String serverId) {
        this.serverId = serverId;
    }

    public Integer getServerPort() {
        return serverPort;
    }

    public void setServerPort(Integer serverPort) {
        this.serverPort = serverPort;
    }

    public String getServerIp() {
        return serverIp;
    }

    public void setServerIp(String serverIp) {
        this.serverIp = serverIp;
    }

    public String getMediaServerIp() {
        return mediaServerIp;
    }

    public void setMediaServerIp(String mediaServerIp) {
        this.mediaServerIp = mediaServerIp;
    }

    public String getMediaServerPort() {
        return mediaServerPort;
    }

    public void setMediaServerPort(String mediaServerPort) {
        this.mediaServerPort = mediaServerPort;
    }
}

application.properties 配置信息

#sip服务器id
fyl.sip.server-id=34020000002000000001
#sip服务器ip地址,默认为0.0.0.0即可
fyl.sip.server-ip=0.0.0.0
#sip服务器监听的端口号
fyl.sip.server-port=5060
#接收流媒体的ip
fyl.sip.media-server-ip=192.168.1.201
#接收流媒体的端口,改端口同时监听udp和tcp 直接发到第三方服务器端口
fyl.sip.media-server-port=10000
#保存摄像头设备信息的redis key
fyl.sip.sip-device-key=fyl_sip_device_key
#接收流媒体的端口,改端口同时监听udp和tcp 该端口用于自己接收rtp ps流
fyl.sip.media-udp-tcp-server-port=10002

SipServerHandler 简单实现

package com.fengyulei.fylsipserver.netty;

import com.fengyulei.fylsipserver.config.ConfigInfo;
import com.fengyulei.fylsipserver.data.Data;
import com.fengyulei.fylsipserver.data.SendDataTask;
import com.fengyulei.fylsipserver.data.SendTipsTask;
import com.fengyulei.fylsipserver.entity.DeviceInfo;
import com.fengyulei.fylsipserver.service.CommonService;
import com.fengyulei.fylsipserver.util.Utils;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//udp直接单例注入
@Component
public class SipServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    private static final Logger logger= LoggerFactory.getLogger(SipServerHandler.class);
    //udp通道 备用
    private Channel channel;
    private ChannelFuture channelFuture;
    public ChannelFuture getChannelFuture() {
        return channelFuture;
    }
    public void setChannelFuture(ChannelFuture channelFuture) {
        this.channelFuture = channelFuture;
        setChannel(channelFuture.channel());
    }
    //一下属性参考配置文件
    private static String serverIp=null;
    private static String serverPort=null;
    private static  String serverId=null;
    private static  String mediaServerIp=null;
    private static String mediaServerPort=null;
    private void setChannel(Channel channel) {
        if(channel==null){
            logger.error("channel null");
            System.exit(1);
        }
        this.channel = channel;
    }
	//配置类
    @Autowired
    private ConfigInfo configInfo;
	//redis
    @Resource(name = "FylSipRedisTemplate")
    private RedisTemplate redisTemplate;

	//业务处理类 可忽略
    @Autowired
    private CommonService commonService;

    private void setDeviceInfo(String deviceId, DeviceInfo deviceInfo){
        redisTemplate.opsForHash().put(configInfo.getSipDeviceKey(),deviceId,deviceInfo);
    }
    private DeviceInfo getDeviceInfo(String deviceId){
        Object obj=redisTemplate.opsForHash().get(configInfo.getSipDeviceKey(),deviceId);
        if(obj==null){
            return null;
        }
        return (DeviceInfo)obj;
    }
    //初始化配置
    @PostConstruct
    private void init(){
        serverIp=configInfo.getServerIp();
        serverPort=configInfo.getServerPort().toString();
        serverId=configInfo.getServerId();

        mediaServerIp=configInfo.getMediaServerIp();
        //mediaServerPort=configInfo.getMediaServerPort();
        mediaServerPort=configInfo.getMediaUdpTcpServerPort().toString();
    }
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket packet) throws Exception {
        //建议捕获异常,防止程序异常退出
        try {
            //gbk解码
            String str=packet.content().toString(Charset.forName("gbk"));
            //去除空包,公网状态下很多空包 应该是服务器端口被探测
            if(str.trim().length()==0){
                return;
            }

            //打印接收信息
            //logger.info("-------------");
            //logger.info(n+str);
            //logger.info(packet.sender().getAddress().getHostAddress());
            //logger.info(String.valueOf(packet.sender().getPort()));
            //logger.info("-------------");
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            //throw e;
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause) throws Exception{
        //关闭之后会导致netty不可用,udp是单通道的 尽量防止异常抛到这里
        ctx.close();
        logger.error(cause.getMessage(),cause);
    }
    //发送udp数据包 注意gbk编码
    private void send(String sendStr,InetSocketAddress inetSocketAddress){
        channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(sendStr,Charset.forName("gbk")), inetSocketAddress));
    }
 }

udp服务器搭建到这结束,不懂的直接留言提问 或滴滴QQ:738126916
下一节讲解 摄像头注册

你可能感兴趣的:(流媒体,gb28181,sip)