当前位置: 首页 > news >正文

一个java类实现UDP代理转发

 概述

实现一个UDP代理服务器,它监听一个指定的端口,将接收到的UDP数据包转发到目标主机,并将目标主机的响应转发回原始客户端。使用线程池来异步处理响应,并使用日志记录器来记录不同级别的日志信息。

源代码

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;public class UDPProxy {private final int listenPort;private final String targetHost;private final int targetPort;private final Map<DatagramSocket, DatagramPacket> downPacketCache = new ConcurrentHashMap<>();private final ThreadPoolExecutor executor = new ThreadPoolExecutor(8, 16,60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(200), new ThreadPoolExecutor.CallerRunsPolicy());private static final Logger logger = Logger.getLogger("UDPProxy");public UDPProxy(int listenPort, String targetHost, int targetPort) {this.listenPort = listenPort;this.targetHost = targetHost;this.targetPort = targetPort;//设置日志级别logger.setLevel(Level.INFO);}public void start() {try (DatagramSocket thisSocket = new DatagramSocket(listenPort)) {byte[] receiveData = new byte[4096];logger.warning("UDP Proxy started, listening on port " + listenPort);Map<InetAddress, DatagramSocket> upSocketCache = new ConcurrentHashMap<>();while (true) {DatagramPacket upPacket = new DatagramPacket(receiveData, receiveData.length);thisSocket.receive(upPacket);byte[] data = upPacket.getData();int length = upPacket.getLength();InetAddress clientAddress = upPacket.getAddress();logger.warning("[UP] Size:" + length + ",from" + clientAddress + ":" + upPacket.getPort());logger.info("[UP] Packet:" + new String(data, 0, length, StandardCharsets.UTF_8));// Forward the packet to the target hostInetAddress targetAddress = InetAddress.getByName(targetHost);DatagramPacket sendPacket = new DatagramPacket(data, length, targetAddress, targetPort);DatagramSocket upSocket = upSocketCache.get(clientAddress);if (upSocket == null) {upSocket = new DatagramSocket();upSocketCache.put(clientAddress, upSocket);downPacketCache.put(upSocket, upPacket);upSocket.send(sendPacket);responseListener(thisSocket, upSocket);} else {upSocket.send(sendPacket);}}} catch (IOException e) {logger.log(Level.SEVERE, "Error in UDPProxy", e);}}private void responseListener(DatagramSocket thisSocket, DatagramSocket upSocket) {executor.execute(() -> {while (true) {byte[] downData = new byte[4096];DatagramPacket downPacket = new DatagramPacket(downData, downData.length);byte[] data = downPacket.getData();InetAddress downPacketAddress;try {upSocket.receive(downPacket);downPacketAddress = downPacket.getAddress();int length = downPacket.getLength();logger.warning("[DOWN] Size:" + length + ",From" + downPacketAddress + ":" + downPacket.getPort());logger.info("[DOWN] Packet:"+ new String(data, 0, length, StandardCharsets.UTF_8));DatagramPacket datagramPacket = downPacketCache.get(upSocket);if (datagramPacket != null) {datagramPacket.setData(data);thisSocket.send(datagramPacket);}} catch (IOException e) {logger.log(Level.SEVERE, "Error in responseListener", e);}}});}public static void main(String[] args) {if (args.length != 3) {logger.warning("Usage: java UDPProxy <listenPort> <targetHost> <targetPort>");System.exit(1);}int listenPort = Integer.parseInt(args[0]);String targetHost = args[1];int targetPort = Integer.parseInt(args[2]);UDPProxy proxy = new UDPProxy(listenPort, targetHost, targetPort);proxy.start();}
}

代码启动

java UDPProxy <listenPort> <targetHost> <targetPort>

  • listenPort:代理服务器监听的端口。

  • targetHost:目标主机的地址。

  • targetPort:目标主机的端口。

 java UDPProxy 12681 192.168.18.76 6666

代码剖析

类和成员变量

  1. 成员变量

    • listenPort:代理服务器监听的端口。

    • targetHost:目标主机的地址。

    • targetPort:目标主机的端口。

    • downPacketCache:用于缓存下行数据包的映射。

    • executor:用于处理响应监听的线程池。

    • logger:用于日志记录的Logger对象。

构造方法

  • 构造方法

    • 初始化listenPorttargetHosttargetPort

    • 设置日志级别为INFO

start方法

  • start方法

    • 创建一个DatagramSocket实例,监听指定的端口。

    • 无限循环接收传入的UDP数据包。

    • 将接收到的数据包转发到目标主机。

    • 使用upSocketCache缓存每个客户端的DatagramSocket实例。

    • 调用responseListener方法监听目标主机的响应。

responseListener方法

  • responseListener方法

    • 使用线程池异步处理目标主机的响应。

    • 接收目标主机的响应数据包。

    • downPacketCache中获取原始客户端的数据包,并将响应数据包发送回原始客户端。

main方法

  • main方法

    • 解析命令行参数,创建UDPProxy实例并启动代理服务器。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • MySQL--查询数据
  • LCR 158. 库存管理 II
  • JVM知识总结(垃圾收集算法)
  • 淘客返利系统中的负载均衡与流量控制策略
  • Windows安装MySQL8.0.X版本归档包(zip包)最新教程
  • 【性能优化】Webpack打包优化
  • Android Gradle开发与应用 (一) : Gradle基础
  • 不同专业方向如何在ChatGPT的帮助下完成选题
  • 【JavaEE初阶】懒汉模式与饿汉模式及指令重排序问题
  • Windows图形界面(GUI)-MFC-C/C++ - 列表框(ListBox) - CListBox
  • 分享一个基于微信小程序的旅游自助拼团系统(源码、调试、LW、开题、PPT)
  • C#MQTT协议应用
  • 解决idea debug/run 启动项目一闪而过的问题
  • Docker 设置代理
  • vscode+linux+opencv环境配置
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • 2017-08-04 前端日报
  • 2019年如何成为全栈工程师?
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • Invalidate和postInvalidate的区别
  • Java程序员幽默爆笑锦集
  • Phpstorm怎样批量删除空行?
  • Python代码面试必读 - Data Structures and Algorithms in Python
  • SAP云平台里Global Account和Sub Account的关系
  • SpiderData 2019年2月13日 DApp数据排行榜
  • uni-app项目数字滚动
  • Vue组件定义
  • 设计模式(12)迭代器模式(讲解+应用)
  • 深入浅出Node.js
  • 使用putty远程连接linux
  • puppet连载22:define用法
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 阿里云ACE认证之理解CDN技术
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • #数学建模# 线性规划问题的Matlab求解
  • $refs 、$nextTic、动态组件、name的使用
  • (007)XHTML文档之标题——h1~h6
  • (4)STL算法之比较
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (C++二叉树05) 合并二叉树 二叉搜索树中的搜索 验证二叉搜索树
  • (Qt) 默认QtWidget应用包含什么?
  • (第61天)多租户架构(CDB/PDB)
  • (二)windows配置JDK环境
  • (附源码)ssm经济信息门户网站 毕业设计 141634
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (四)JPA - JQPL 实现增删改查
  • (幽默漫画)有个程序员老公,是怎样的体验?
  • (转载)虚函数剖析
  • .NET C# 使用 iText 生成PDF
  • .NET国产化改造探索(三)、银河麒麟安装.NET 8环境
  • .NET设计模式(11):组合模式(Composite Pattern)
  • @Builder用法
  • @DependsOn:解析 Spring 中的依赖关系之艺术