精华内容
下载资源
问答
  • java实现udp打洞,服务器转发消息

    千次阅读 2018-09-26 15:09:24
    关于服务器转发 转载地址:https://blog.csdn.net/qq_38109425/article/details/77096059

    关于服务器转发
    这个偏向于客户端一对一发送和接收
    转载地址:https://blog.csdn.net/qq_38109425/article/details/77096059

    展开全文
  • // 启动udp服务器,接收消息,转发消息 public void startServer() throws Exception { //启动接收的UDP端口服务器, InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1", 13000); ...
  • JAVA实现UDP反向代理

    千次阅读 2017-11-12 16:22:48
    JAVA实现TCP协议的反向代理非常容易,只用不到100行代码就能搞定,只需两个Socket,3条线程,进行输入流与输出流之间互相读写就可以了,可以承载所有TCP协议层以上的流量,比如HTTP(s),FTP,sFTP,邮件,即时通讯...

    用JAVA实现TCP协议的反向代理非常容易,只用不到100行代码就能搞定,每一个连接只需两个Socket,3条线程,进行输入流与输出流之间互相读写就可以了,可以承载所有TCP协议层以上的流量,比如HTTP(s),FTP,sFTP,邮件,即时通讯等等。其效果和HAProxy或者Nginx的TCP反向代理差不多,而且如果客户端的并发数比较大的情况,还可以使用JAVA的NIO和AIO框架,降低服务器资源的开销。

    对于UDP协议来说,它是无连接无状态的点对点协议,所以与TCP协议比起来会有很大的不同,主要体现在:TCP是有链接协议,所以当有很多个客户端访问代理程序时,代理会转发他们的请求给服务器端,服务器响应数据给代理程序后,代理程序清楚的知道这个响应应该发给哪个客户端,并将数据发送回去。其逻辑如下

    1、客户端发起一个Socket,绑定端口50000,目标地址为代理服务器8080。代理程序开启ServerSocket,绑定端口8080,于是一条客户端5000到代理端8080的连接就建立起来,客户端Socket通过OuputStream把数据发送给代理端的InputStream。


    2、服务端监听到连接建立之后,立即new Socket,绑定51000端口,目标端口为真实服务器的80端口,于是一条代理服务器50000到真实服务器80的连接就建立起来。


    3、然后代理服务器新建两个线程,一条将客户端的连接的InputStream写入到真实服务器连接的OutputStream,另一条线程将服务端连接的InputStream写入到客户端连接的OutputStream,就完成了一次代理转发。


    在这个过程中,客户端开放了一个端口50000,代理程序开放两个端口8080和51000,真实服务器开放了一个端口80


    如果有n个客户端,那么每个客户端也只开放一个端口,代理程序开放1+n个端口,真实服务器始终开放一个端口。


    如果有n个客户端,每个客户端建立m条并发连接,那么每个客户端开放m个端口,代理程序开放1+m*n个端口,真实服务器开放一个端口。


    从上面可以看出,对于TCP来说,每一条连接使用不同的端口进行区分,当一条连接建立起来时,客户端会监听一个49000以上的端口,代理端使用代理端口与其连接,但是代理端建立的与真实服务器的连接也会在代理端开放一个49000以上的端口,这个端口号和客户端开放的端口号一般是不同的。这样一来,在上面的例子中,服务端发送到代理端51000的数据包很自然的被代理端转发给客户端50000端口,一一映射不会出错。即使再多的客户端连接也不会混淆。


    但是UDP协议是无连接的协议,它也可以仿照TCP协议的转发方式进行工作,过程如下

    1、客户端发起一个DatagramSocket,绑定端口50000,目标地址为代理服务器的53端口。代理程序也new 一个 DatagramSocket,监听53端口。于是客户端就可以向代理端发送数据包了。

    2、代理端收到数据包之后,有两个选择,第一是用接收客户端数据包的DatagramSocket把这个数据包发送到真实服务器,不过这样就没法再接收客户端发来的后续数据包了,所以一般情况下,代理程序会new DatagramSocket,把刚刚收到的DatagramPacket修改一下目标地址发送给真实的服务器。

    3、现在代理端又有两个选择了,由于UDP不像TCP那样有流的概念,所以我们无法拿到输入输出流,只能操作数据包,而且是单向的操作数据包。一个方案是用刚刚向真实服务器发包的DatagramSocket接收服务端返回的数据包,另一个方案是不接受数据包继续转发下一个数据包。

    第一个方案我们可以接收到服务器的返回数据,缺点是没法再利用这个DatagramSocket发送第二个数据包了,第二种方案可以流畅的转发客户端的数据包到服务端,不过客户端就收不到服务端的响应了。


    所以此时,我们需要根据业务需求制定相关的转发策略了,这里我主要分为了两种类型

    1、DNS型转发:客户端发送一个数据包需要服务端马上返回一个数据包实现业务逻辑,比如DNS。单个数据包最大为65536字节,某些环境下还会更小。

    2、P2P隧道转发:客户端向服务端发送一连串的多个数据包,并且服务端也向客户端发送多个数据包,数据包收发并不是一问一答的关系,而是发送和接收同时进行。


    逻辑上来说第一种方式是第二种方式的子集,只不过为了节约资源开销,第一种方式在服务端返回数据包以后立即关闭Socket,从而节约内存和网络资源。有些应用比如OpenVPN的udp模式就没有应答的概念,而是输入和输出像流一样同时进行。从代码实现上来说,第二种方式比较容易实现一些,首先建立两个DatagramSocket,一个监听在本地端口,用于接收客户端发来的数据包并转发真实服务器的响应;另一个把目的地址指向真实服务器,用于向真实服务器发送和接收数据包。在代理端的DatagramSocket通过receive()方法收到一个DatagramPacket之后,新建两个线程,一个负责接收客户端的数据包并向真实服务器发送数据包,另一个负责接收服务器发的数据包并修改目的地址发送给客户端。如此一来,通过两个DatagramSocket两个线程就实现了一个P2P的UDP转发隧道。


    注意,UDP报文是没有FIN这种标识符的,所以代理服务器无法知道连接是否被主动关闭,只能通过超时时间去判断,所以为了连接保活,需要客户端定时发送心跳包。另外,如果端口是固定的话也可以让代理服务器建立永久的转发通道,只不过这样资源开销比较大,不适合高并发的场景。


    上面的两种方式都面临一个问题,就是并发访问的问题。所谓并发访问就是代理服务器反向代理了一个端口,然后有不止一个客户端链接这个端口,或者一个客户端调用了多个程序并发访问该端口,那么如果代码上不做处理就会引起UDP数据包传递的混乱。


    举个例子,比如客户端A向DNS反向代理发送了一个DNS请求,还没收到返回消息的时候客户端B也发出了一个DNS请求,这时代理服务器收到了真实服务器发来的客户端A请求的响应,由于UDP是无连接协议,所以此时代理服务器并不知道应该把数据包发到哪去。不向TCP那样获取到Socket之后直接写流就可以了。所以需要我们用JAVA代码去维护一个路由表。也就是说,当用户A请求DNS的时候,记录下A的源IP和端口号,然后new DatagramSocket向真实服务器发出请求,然后再用这个DatagramSOcket的receive()去接收返回数据包,然后按照刚才记录的A的ip和端口把数据发送回去,同理如果多个客户端来请求,那么就需要new 多个DatagramSOcket并记录每个请求的源IP和端口。如果多个客户端复用同一个DatagramSocket向真实服务器发送消息,虽然可以把数据包发送出去,但是收到响应以后你就无从获知是哪个客户端请求的了,所以这样做就会导致数据包错发的问题,会出现把客户端A请求DNS的响应错发给B,B本来请求的是www.csdn.com的IP,但是代理却发给它www.baidu.com的IP,这是和TCP最大的区别。如下图黄色图标标出的请求和相应信息,就发生了这种错乱:



    总结一下过程如下

    1、一个客户端发出一个DNS请求到代理服务器53端口,开放端口50000监听返回值。代理端使用两个DatagramSocket,一个监听53端口,与客户端收发数据,另一个开放51000端口用来与真实服务器收发数据。真实服务器只开放一个53端口

    2、n个客户端各发出一个DNS请求,每个客户端都开放50000端口监听返回数据,代理端使用1+n个DatagramSocket,开放53和另外n个UDP端口,并在内存中记录好每个客户端的源IP和端口,第一个DatagramSocket用来和所有客户端收发数据,后n个用来和真实服务器收发数据。

    3、n个客户端都同时发出m个DNS请求,每个客户端开放50000,50001,50002...接收返回数据,代理端使用1+m*n个DatagramSocket,开放53和m*n个UDP端口,记录好每一个请求的源IP和端口,第一个DatagramSocket用来和所有客户端收发数据,后m*n个用来和真实服务器收发数据。


    总的来说,有一点很重要,那就是同一会话使用同一个DatagramSocket,不同的会话使用不同的DatagramSocket,每一个UDP有两个会话,其中客户端和代理服务器的会话是所有客户端公用一个DatagramSocket,就像TCP里面的ServerSocket,代理服务器和真实服务器之间每个会话使用不同DatagramSocket,就像TCP里面为每个连接new的SOcket对象。当真实服务器响应了数据之后,一定要弄清楚该数据是发给哪个客户端的,而辨别的要点就是端口号,将代理端开放的端口和客户端发送的端口做一一映射的关系表,就不会错乱了。


    关于Java实现UDP反向代理隧道的源代码可以看这里:https://github.com/AlexZhuo/java-tcp-tunnel

    打成Jar包并且把Main.java设为主类,然后执行下面语句(JRE 1.7以上版本)

    单个数据包收发(一发必有一收)

    java -jar tcptunnel-0.1.0.jar 53 8.8.8.8 53 --udp-dns
    多个数据包收发(流式发送)

    java -jar tcptunnel-0.1.0.jar 7000 xxx.xxx.xxx.xxx 9999 --udp-tun

    展开全文
  • Java实现UDP通信过程

    万次阅读 多人点赞 2019-01-22 17:32:17
    TCP是一种面向连接的传输层协议,而UDP是传输层中面向无连接的协议,故传送的数据包不能保证有序和不丢失,实现UDP通信主要用到了两个类:DatagramPacket和DatagramSocket。 DatagramSocket 这个类用来表示发送和...

    TCP是一种面向连接的传输层协议,而UDP是传输层中面向无连接的协议,故传送的数据包不能保证有序和不丢失,实现UDP通信主要用到了两个类:DatagramPacket和DatagramSocket。

    DatagramSocket
    这个类用来表示发送和接收数据包的套接字。

    //构造方法,创建数据报套接字并将其绑定到本地主机上的指定端口
    DatagramSocket socket = new DatagramSocket(0);	
    

    DatagramPacket
    表示数据报包,用来实现无连接的包的投递服务。这些数据包选择不同的路由,经过计算机的存储转发,最终到达目的计算机。所以到达的数据包和发送时的顺序不一定会相同。
    在这里插入图片描述

    Sever端程序

    一,调用DatagramSocket(int port)创建一个数据报套接字,绑定在指定端口上;
    二,调用DatagramPacket(byte[] buf,int length),建立一个字节数组来接收UDP包;
    三,调用DatagramSocket.receive();
    四,最后关闭数据报套接字。

    Client端程序
    一,调用DatagramSocket()创建一个数据报套接字;
    二,调用DatagramPacket(byte[] buf,int offset,InetAddress address,int port),建立要发送的UDP包
    三,调用DatagramSocket类的send方法发送数据包;
    四,关闭数据报套接字。

    数据报套接字发送成功后,相当于建立了一个虚连接,双方可以发送数据。

    实例

    服务器端:

    /*
     * 服务器端,实现基于UDP的用户登陆
     */
    public class UDPServer {
        public static void main(String[] args) throws IOException {
            /*
             * 接收客户端发送的数据
             */
            // 1.创建服务器端DatagramSocket,指定端口
            DatagramSocket socket = new DatagramSocket(8800);
            // 2.创建数据报,用于接收客户端发送的数据
            byte[] data = new byte[1024];// 创建字节数组,指定接收的数据包的大小
            DatagramPacket packet = new DatagramPacket(data, data.length);
            // 3.接收客户端发送的数据
            System.out.println("****服务器端已经启动,等待客户端发送数据");
            socket.receive(packet);// 此方法在接收到数据报之前会一直阻塞
            // 4.读取数据
            String info = new String(data, 0, packet.getLength());
            System.out.println("我是服务器,客户端说:" + info);
     
            /*
             * 向客户端响应数据
             */
            // 1.定义客户端的地址、端口号、数据
            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            byte[] data2 = "欢迎您!".getBytes();
            // 2.创建数据报,包含响应的数据信息
            DatagramPacket packet2 = new DatagramPacket(data2, data2.length, address, port);
            // 3.响应客户端
            socket.send(packet2);
            // 4.关闭资源
            socket.close();
        }
    }
    

    客户端:

    /*
     * 客户端
     */
    public class UDPClient {
        public static void main(String[] args) throws IOException {
            /*
             * 向服务器端发送数据
             */
            // 1.定义服务器的地址、端口号、数据
            InetAddress address = InetAddress.getByName("localhost");
            int port = 8800;
            byte[] data = "用户名:admin;密码:123".getBytes();
            // 2.创建数据报,包含发送的数据信息
            DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
            // 3.创建DatagramSocket对象
            DatagramSocket socket = new DatagramSocket();
            // 4.向服务器端发送数据报
            socket.send(packet);
     
            /*
             * 接收服务器端响应的数据
             */
            // 1.创建数据报,用于接收服务器端响应的数据
            byte[] data2 = new byte[1024];
            DatagramPacket packet2 = new DatagramPacket(data2, data2.length);
            // 2.接收服务器响应的数据
            socket.receive(packet2);
            // 3.读取数据
            String reply = new String(data2, 0, packet2.getLength());
            System.out.println("我是客户端,服务器说:" + reply);
            // 4.关闭资源
            socket.close();
        }
    }
    
    展开全文
  • java实现UDP,TCP网络穿透 完整demo

    千次阅读 2018-01-23 15:14:54
  • java UDP实现局域网广播

    千次阅读 2015-11-07 18:37:09
    使用javaUDP进行广播,要分两步走,首先要加入到广播组地址,其次要建立套接字传输信息 关于广播,涉及到MulticastSocket,他用于接收广播的信息,前提是要将它加入到广播组,组播的地址是保留的D类地址从224.0....
  • 基于java实现UDP多用户聊天应用

    千次阅读 2014-01-10 12:20:11
    第一次写博客,还请大家多多指教 因为最近做了一个关于计算机网络的课程设计,是一个多用户聊天软件,实现过程比较简单,现在就拿来和大家分享一下,如果...Setusername.java package zhonghui.client; import j
  • Netty4实现UDP向TCP转发

    千次阅读 2014-11-12 11:05:30
    TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个...UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。
  • 学习使用Java开发语言做计算机音频数据采集、压缩、转发功能,从而实现双向通话功能。采集数据频率为8KHz、16bit、单通道、小端格式,数据转发采用G711A压缩传输。 二、音频采样率 1. 参考百度百科 为了测试语音通话...
  • java基于UDPSocket的通信

    2018-05-25 09:38:10
    ChatClient:package udp;import javax.swing.*;import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.FlowLayout;import java.awt.Toolkit;import java.awt.event.*;import java.io.*;import ...
  • Netty 实现 UDP 通讯

    2021-03-03 16:27:18
    Netty 实现 UDP 通讯 本文包括 UDP 一些基础知识和使用 Netty 完成 UDP 单播、组播和广播等多多种方式通讯。
  • JAVA UDP聊天室

    2015-08-21 19:37:05
    本文为使用UDP 进行数据传输的一个聊天室应用,使用JAVA语言开发的聊天室在目前的实际中应用很少,写这个例子的原因的进一步理解CS模式编程,掌握这种思想。  本例子分为客户端和服务器两个部分,客户端输入想要...
  • 在空余时间用Java写了一个转发服务器,可以用于转发文字、图片、音频、视频等数据。
  • Java UDP套接字程序设计 UDP特点: (1)UDP有别于TCP,有自己独立的套接字(IP+PORT),它们的端口号不冲突。和TCP编程相比,UDP在使用前不需要进行连接,没有流的概念。如果说TCP协议通信与电话通信类似,那么UDP通信...
  • 最近的项目需求,让多个Android应用共用一条链路,采用AIDL Service 觉得耦合度比较高,于是想想能不能用UDP本地转发的方式来将数据传送到那条链路所在的Service中。 于是写了下面两个测试代码。没有定义协议,直接...
  • 实现一个基于UDP的聊天程序。具体功能: (1)能实现多客户端之间的群聊功能; (2)客户端的聊天记录可以存储在文件或数据库中; (3)客户端、服务器端均能显示在线用户列表; (4)客户可以查看以往聊天记录; ...
  • 首先得简单介绍下UDPUDP( User Datagram Protocol )协议是用户数据报,在网络中它与TCP协议一样用于处理数据包。在OSI模型中,在第四层——传输层,处于IP协议的上一层。它是一种无连接的协议,每个数据报都是一...
  • JAVA TCP/UDP网络编程

    2016-03-02 16:56:57
    JAVA TCP/UDP网络编程学习
  • java UDP协议程序设计

    2014-04-14 14:49:00
    UDP协议的简介 UDP协议是一种面向无连接不可靠的协议,也就是在进行数据通讯之前发送端和接收端无需进行连接,发送端要发送数据, ...所以在实现UDP协议的程序中,最关键是如何实现UDP的数据报. JAVA中...
  • 模拟集群转发udp单播项目,java实现,netbean开发环境,包含客户端和服务端。
  • udp穿透简单讲解和实现(Java)

    千次阅读 2016-06-01 13:17:47
    在上一小节中了解到了通过浏览器自带的Webrtc功能来实现P2P视频聊天。在HTML5还没有普及和制定Webrtc标准的前提下,如果要在手机里进行...所以本次要了解一下udp进行穿透(打洞)。 还是进入正题吧,了解P2P。
  • UDP连接 TCP连接
  • java UDP协议发送数据4. java UDP协议接收数据5. java TCP协议发送数据6. java TCP协议接收数据 1. 概述 1.1 网络协议 通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要...
  • UDP实现聊天

    千次阅读 2019-01-30 10:12:11
    从简单到复杂,首先简单介绍一下怎么利用UDP实现客服端发送消息给服务器端吧: 发送、接受消息过程大概如下: 服务器端:创建DatagramSocket对象用于打开指定端口并监听,然后用创建一个DatagramPacket,利用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,455
精华内容 6,182
关键字:

java实现udp转发

java 订阅