UDP服务端的编写示例

1 说明

      最近获得了一个需求,要求是编写一个程序用于接收传递过来的XML字符串,将该字符串保存为指定目录下的xml文件并记录日志。为了提高传输效率,我才用了UDP协议来编写程序,本文主要讲解用SpringBoot框架编写UDP服务端程序,并编写了一个用于测试的客户端程序。

1.1 UDP 的主要特点

  1. UDP 是无连接的,即发送数据之前不需要建立连接(发送数据结束时也没有连接可释放),减少了开销和发送数据之前的时延
  2. UDP 使用尽最大努力交付,即不保证可靠交付,主机不需要维持复杂的连接状态表
  3. UDP 是面向报文的,发送方的 UDP 对应用程序交下来的报文,在添加首部后就向下交付 IP 层。UDP 对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界
  4. UDP 没有拥塞控制,网络出现的拥塞不会使源主机的发送速率降低。这对某些实时应用是很重要的
  5. UDP 支持一对一、一对多、多对一和多对多的交互通信
  6. UDP 的首部开销小,只有8个字节,比 TCP 的20个字节的首部要短
    在这里插入图片描述

1.2 存在的问题

  1. 某些实时应用需要使用没有拥塞控制的 UDP,但很多的源主机同时都向网络发送高速率的实时视频流时,网络就有可能发生拥塞,导致大家都无法正常接收。
  2. 还有一些使用 UDP 的实时应用,需要对 UDP 的不可靠传输进行适当的改进,以减少数据的丢失。应用进程可以在不影响应用的实时性的前提下,增加一些提高可靠性的措施,如采用前向纠错或重传已丢失的报文

2 服务端编写示例

代码清单:

  1. UdpConfig.java
  2. FileXmlServer.java
  3. MsgEntity.java

1 UdpConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.ip.udp.UnicastReceivingChannelAdapter;

/**
 * UDP配置
 *
 * @author 一朝风月
 * @date 2021/12/16 14:54
 */
@Configuration
public class UdpConfig {
    @Bean
    public IntegrationFlow integrationFlow() {
        return IntegrationFlows.from(new UnicastReceivingChannelAdapter(12345))
                .handle("FileXmlServer", "handleMessage")
                .get();
    }
}

2 FileXmlServer.java

import com.alibaba.fastjson.JSON;
import com.css.filexml.model.MsgEntity;
import com.css.filexml.utils.XMLUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Service;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Xml报文存储服务
 *
 * @author 一朝风月
 * @date 2021/12/16 14:59
 */
@Service("FileXmlServer")
@Slf4j
public class FileXmlServer {
    /**
     * 文件存储路径
     */
    @Value("${filePath}")
    private String filePath;
    /**
     * 日志路径
     */
    @Value("${logPath}")
    private String logPath;
    /**
     * 日志文件名
     */
    @Value("${logFileName}")
    private String logFileName;

    /**
     * 处理消息
     *
     * @param message 消息
     */
    public void handleMessage(Message message) {
        String data = new String((byte[]) message.getPayload());
//        SendMsg msg = JSON.parseObject(data, SendMsg.class);
        MsgEntity msg = JSON.parseObject(data, MsgEntity.class);
        String filePathName = filePath + File.separator + msg.getUuid() + ".xml";
        XMLUtil.convertToXml(msg, filePathName);
        File fileOk = new File(filePathName + ".ok");
        if (new File(filePathName).exists()) {
            XMLUtil.convertToXml(msg, fileOk.getPath());
        }
        try {
            printLog(JSON.toJSONString(msg));
        } catch (IOException e) {
            e.printStackTrace();

        }
    }

    /**
     * 记录日志
     *
     * @param msg 消息
     * @throws IOException 异常
     */
    private void printLog(String msg) throws IOException {
        File filePath = new File(logPath);
        if (!filePath.exists()) {
            filePath.mkdirs();
            new File(logPath + File.separator + logFileName).createNewFile();
        }
        BufferedWriter out = new BufferedWriter(new FileWriter(logPath + File.separator + logFileName, true));
        String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date());
        out.write(currentTime + "\t" + msg + "\n");
        out.close();
    }
}

3 MsgEntity.java

/**
 * 消息内容实体类
 *
 * @author 一朝风月
 * @date 2021/12/21 11:44
 */
public class MsgEntity {
    /**
     * UUID
     */
    private String uuid;
    /**
     * 字段1
     */
    private String msg1;
    /**
     * 字段2
     */
    private String msg2;
    /**
     * 字段3
     */
    private String msg3;

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getMsg1() {
        return msg1;
    }

    public void setMsg1(String msg1) {
        this.msg1 = msg1;
    }

    public String getMsg2() {
        return msg2;
    }

    public void setMsg2(String msg2) {
        this.msg2 = msg2;
    }

    public String getMsg3() {
        return msg3;
    }

    public void setMsg3(String msg3) {
        this.msg3 = msg3;
    }
}

3 测试程序

3.1 例程

1 FileXmlClient.java

import com.alibaba.fastjson.JSON;
import com.css.filexml.model.MsgEntity;
import org.springframework.integration.ip.udp.UnicastSendingMessageHandler;
import org.springframework.integration.support.MessageBuilder;

/**
 * 客户端
 *
 * @author 一朝风月
 * @date 2021/12/16 20:06
 */
public class FileXmlClient {
    private String host;
    private Integer port;

    public FileXmlClient(String host, Integer port) {
        this.host = host;
        this.port = port;
    }

    public void send(MsgEntitysendMsg) {
        UnicastSendingMessageHandler handler =
                new UnicastSendingMessageHandler(host, port);

        String payload = JSON.toJSONString(sendMsg);
        handler.handleMessage(MessageBuilder.withPayload(payload).build());
    }
}

2 Test.java

import com.css.filexml.client.FileXmlClient;
import com.css.filexml.model.MsgEntity;

/**
 * 测试程序
 *
 * @author 一朝风月
 * @date 2021/12/16 15:07
 */
public class Test {
    public static void main(String[] args) {
        FileXmlClient fileXmlClient = new FileXmlClient("127.0.0.1", 12345);
        MsgEntity msgEntity = new MsgEntity();
        msgEntity.setUuid("1234567890");
        fileXmlClient.send(msgEntity);
    }
}

3.2 测试结果

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<msgEntity>
    <uuid>1234567890</uuid>
</msgEntity>

2021-12-21 12:03:40.973	{"uuid":"1234567890"}

4 gitee项目链接

gitee项目链接

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值