网络编程套接字(3)——Java数据报套接字(UDP协议)

这篇具有很好参考价值的文章主要介绍了网络编程套接字(3)——Java数据报套接字(UDP协议)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、Java数据报套接字通信模型

二、UDP数据报套接字编程

1、DatagramSocket

        (1)DatagramSocket构造方法

        (2)DatagramSocket方法

2、DatagramPacket

        (1)DatagramPacket构造方法

        (2)DatagramPacket方法

3、InetSocketAddress

三、代码示例:回显服务器

        1、服务器代码

     代码解析

          2、客户端代码

代码解析

3、创建DatagramPacket三种不同的参数场景

4、执行代码

5、客户端和服务器交互的过程


一、Java数据报套接字通信模型

        对于UDP协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且一次发送全部数据报。

        java中使用UDP协议通信,主要基于DatagramSocket类来创建数据报套接字,并使用DatagramSocket作为发送或接收的UDP数据报。对于一次发送及接收UDP数据报的流程如下:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        以上只是一次发送端的UDP数据报发送,及接收端的数据报接收,并没有返回的数据。也就是只有请求,没有响应。对于一个服务端来说,重要的是提供多个客户端的请求处理响应,流程如下:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言


二、UDP数据报套接字编程

        Java把系统原生的API进行了封装,供我们使用,以下是API介绍,主要核心的类有两个:DatagramSocketDatagramPacket

1、DatagramSocket

        操作系统中,有一类文件就叫做 socket 文件,普通文件、目录文件是在硬盘上的,socket 文件抽象表示了 “网卡” 这样的硬件设备

        进行网络通信最核心的硬件设备就是 网卡

                通过网卡发送数据,就是写 socket 文件。

                通过网卡接受数据,就是读 socket 文件。

        DatagramSocket是 UDP 的 Socket,负责对 socket 文件的读写也就是借助网卡发送和接收数据报

        (1)DatagramSocket构造方法

方法签名 方法说明
DatagramSocket()

创建一个UDP数据报套接字的Socket,绑定到本机

任意一个随机端口(一般用于客户端)

DatagramSocket(int port)

创建一个UDP数据报套接字的Socket,绑定到本机

指定的端口(一般用于服务端)

        (2)DatagramSocket方法

方法签名 方法说明
void receive(DatagramPacket p)

从此套接字接受数据报(如果没有收到数据报,该

方法会阻塞等待)

void send(DatagramPacket p) 从此套接字发送数据包(不会阻塞等待,直接发送)
void close() 关闭此数据报套接字

2、DatagramPacket

        DatagramPacket是UDP Socket发送和接收的数据报

        UDP面向数据报,每次发送接受数据的基本单位,就是一个UDP数据报,表示了一个UDP数据报。

        (1)DatagramPacket构造方法

方法签名 方法说明
DatagramPacket(byte[] buf, int length)

构造一个DatagramPacket以用来接收数据报,接收的

数据保存在字节数组(第一个参数buf)中,接收指定

长度(第二个参数length)

DatagramPacket(byte[] buf, int offset, int length,

SocketAddress address)

构造一个DatagramPacket以用来发送数据包,发送的

数据为字节数组(第一个参数buf)中,从0到指定长度

(第二个参数length)。address指定目的主机IP和端口号

        (2)DatagramPacket方法

方法签名 方法说明
InetAddress getAddress()

从接收的数据报中,获取发送端主机IP地址;

或从发送的数据报中,获取接收端主机IP地址

int getPort()

从接收的数据报中,获取发送端主机的端口号;

或从发送的数据报中,获取接收端主机的端口号

byte[] getData() 获取数据报中的数据

        构造UDP发送的数据报时,需要传入SocketAddress,该对象可以使用InetSocketAddress来创建。

3、InetSocketAddress

        InetSocketAddress (SocketAddress的子类) 构造方法:

方法签名 方法说明
InetSocketAddress(InetAddress addr, int port) 创建一个Socket地址,包含IP地址和端口号

三、代码示例:回显服务器

        在网络编程中,回显服务器是最简单的程序了,相当于网络编程的 hello world

        功能:服务器接受客户端的请求,返回响应。(根据客户端发出的请求,返回啥响应,要更具实际的业务场景来编写代码,这里的案例没啥业务逻辑)

        1、服务器代码

public class UdpEchoServer {
    private DatagramSocket socket = null;
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);//参数里面指定端口号
    }
    //服务器的启动逻辑
    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            //1、读取请求并解析
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);
            //把读到的字节数组,转换成字符串,方便后面的逻辑处理
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            //2、根据请求计算响应(对于回显服务器来说,这一步啥也不用做)
            String response =process(request);
            //3、把响应返回给客户端
            //构造一个 DatagramPacket 作为响应对象
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);
            //打印日志
            System.out.printf("[%s : %d] req: %s resp: %s", requestPacket.getAddress().toString(),
                    requestPacket.getPort(), request, response);
            System.out.println();
        }
    }
    //计算响应计算方法(这里没逻辑)
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer udpEchoServer = new UdpEchoServer(9090);
        udpEchoServer.start();
    }
}

     代码解析

        第一步需要创建 DatagramSocket 对象,接下来要操作网卡,都是通过 socket 对象来完成的。socket 对象是在内存中的,操作这个对象就能影响到网卡类似遥控器。

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        这个程序需要绑定 / 关联上一个操作系统上的端口号,所以构造方法里传的就是端口号。

        端口号:是一个整数,用来区分一个主机上进行网络通信的程序。一个主机上的一个端口号只能被一个进程绑定,如果一个端口被进程A绑定了,如果进程B绑定这个端口,就会失败,除非进程A释放了这个端口,进程B才能绑定上。

        反过来,一个进程可以绑定多个端口,很常见。端口号和 socket 对象是一一对应的,如果一个进程中有多个socket对象,那这个进程就能绑定多个端口了。

        如图的异常:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        该异常是网络很常见的异常,通常表示 socket 创建失败,比如说端口号被别的进程占用了,就会抛出该异常。

        如图的循环:

        网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        对于服务器来说,需要不停的收到请求,返回响应。一个服务器在单位时间能处理的请求越多,那这个服务器就越厉害。

        服务器往往是 7 * 24 小时运行的,要持续不断的运行下去,所以,这里的 while(true) 没有退出的必要,如果要退出,简单粗暴的办法就是 “杀进程”,在 linux 中有个结束进程的命令:kill,带有 -9 是强制退出,不带的话就是告诉进程,你该挂了,而进程可以选择继续工作,也可以选择自挂东南枝。所以才有了 杀进程 这一说法。

        对于内部的逻辑要写的就是如下图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        receive方法里的参数如图:

 网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        里面放的参数是 DatagramPacket 对象,而此处它是 “输出型参数”,前面的文件IO涉及到了,像InputStream里的read方法,里面参数也是输出型参数(字节数组)

        实际上,DatagramPacket 内部就会包含一个字节数组

        如图的 DatagramPacket:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        通过这个字节数组来保存收到的消息正文 (应用层数据包) ,也就是 UDP 数据报的载荷部分。后面的数字大小,就是这个 载荷 有多长,可以灵活设置。

        如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        这里的 receive 就能从网卡读到一个 UDP 数据报,这个数据报是被放到 requestPacket 对象中的,其中的 载荷部分 就放到 requestPacket 内置的 字节数组 中了,另外,报头部分也被 request 的其他属性保存了。

        除了 UDP 报头之外,还有其他信息,比如 收到的数据源IP,可以通过 requestPacket 知道源IP 和 源端口

        如果服务器没有收到请求,服务器就会在这里阻塞,等到有客户端的请求过来了,再receive,然后执行下面的逻辑。

        如图,拿到数据报后的解析:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        这里是基于字节数组构造出的String的,字节数组里的内容不一定是二进制数据,也可能是文本数据,把文本数据交给 String 来保存,也是恰到好处,就算是二进制数据,Java的String 也是可以保存的。

        上面的 0 是指的是从 0 号位置开始构造String

        getLength 是获取字节数组中有效数据的长度,用这么长来构造String,这里的有效长度,不一定是4096,4096是最大长度,一定要使用有效长度来构造,如果使用4096,就会生成一个非常长的 String ,后半部分都是空白。

        客户端发来的请求数据,说是存在socket文件中,但要注意,此处的数据是在 socket 的内存缓冲器的,并不是在硬盘上,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        这个代码,要根据请求构造 / 计算响应通过 process 方法来完成这个工作

        由于此处是回显服务器,所以就单纯的 return 了,如果是一些具有特点业务的服务器,process 就可以写其他任何你想要的逻辑了。

        当计算完响应,可以 send 时,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        这里的 send 也需要放 DatagramPacket 的对象,作为参数。

        DatagramPacket 的对象参数第一个:不是空白字节数组,直接把 String 包含的字节数组给拎过来了;

        第二个参数:单位是字节,得到字节的长度;这里不能写成:response.length(),这指的是字符个数 ,单位是字符;字符和字节个数肯定是不一样的,除非是标准ASCII表的字符

        第三个参数:requestPacket是客户端发生过来的数据报,得到INetAddress 对象,这个对象包含了 IP 和 端口号,也就是和服务器对端(对应的客户端)的 IP 和 端口。这里是把请求中的源 IP 和 源端口,作为响应的 目的IP 和 目的端口,此时就可以做到把响应返回给客户端了。

        从上面代码中可以看到:

        UDP 是无连接的通信:UDP socket 自身不保存对端的 IP 和 端口,而是在每个数据报中都有一个,另外代码中也没有 “建立连接” 、“接受连接” 的操作。

        不可靠传输:上面代码中体现不到。

        面向数据报:send 和 receive 都是以 DatagramPacket 为单位的。

        全双工:一个 socket 既可以发送,也可以接收。

        打印日志那里:打印客户端 IP 是以点分十进制 的形式打印的,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        后面陆续是打印客户端端口号,打印请求字符串,打印响应字符串

        我们设置服务器端口时的注意事项,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        上面的端口号你可以指定任何你想要的端口,但也是有范围的,通常来说,使用的端口号x范围是:1024 < x < 65535。

        但是也有前提,确保你当前这个端口在当前机器上没有被其他端口占用,如果指定了端口,创建服务器失败的话,换个端口就好了

          2、客户端代码

public class UdpEchoClient {
    private DatagramSocket socket = null;
    String serverIp;
    int serverPort;
    //此处使用的IP是点分十进制的风格,例如:192.168.0.0
    public UdpEchoClient(String serverIp, int serverPort) throws SocketException {
        socket = new DatagramSocket();
        this.serverIp = serverIp;
        this.serverPort = serverPort;
    }

    public void start() throws IOException {
        System.out.println("客户端启动");
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.print("->");
            //要做四个事情
            //1、从控制台读取要发送的请求数据
            if(!scanner.hasNext()) {
                break;
            }
            String request = scanner.next();
            //2、构造请求并发送
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),
                    request.getBytes().length, InetAddress.getByName(serverIp), serverPort);
            socket.send(requestPacket);
            //3、读取服务器的响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);
            //4、把响应显示到控制台上
            String response = new String(responsePacket.getData(), 0, responsePacket.getLength());
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1", 9090);
        udpEchoClient.start();
    }
}

代码解析

        首先要创建 socket 对象,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        此处是不需要手动指定端口号,让系统随机分配一个端口号即可,而构造方法中传的是服务器IP 和 服务器端口,所以要保存一下,把它们设成客户端的属性。而源 IP 就是客户端的 本机IP,源端口就是 系统分配的空闲端口。

        对于客户端来说,系统随机分配的端口,是空闲的,但如果手动指定端口,是可用,但有可能被别的进程占用。

        同理,服务器端口不一定就100%不会被别的进程占用,但服务器这个机器,是在程序员手里的,程序员可以事先知道服务器上都有哪些端口被使用,就比较有谱;普通用户千千万,其中电脑上的环境也会千差万别,天知道用户按照了什么鬼程序,把你的服务器端口给占用了,你的程序也会因为端口的绑定失败而无法启用,用户就会怪在你头上,说你代码写的不行。

        输入请求,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        注意:从控制台读取,使用 scanner 读取字符串,最好是使用 next,而不是nextLine.

        如果使用 nextLine 读取,就需要手动输入换行符:enter键 来控制。由于 enter键 不仅仅会产生 \n 字符,还好产生其他字符,就会导致读取到的内容容易出问题。

        使用 next 其实是以 “空白符” 作为分隔符,分隔符包括但不限于 换行,回车,空格,制表符,垂直制表符...

        如果是从文件中读取的,那就无所谓了,因为文件中有各种字符。

        构造请求并发送,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        此处创建的 DatagramPacket 对象,里面参数放的先后分别是:请求字符串的字节数组,字节数组的长度,服务器的IP地址,服务器端口。

        读取服务器的响应,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言        是用新的字节数组存放响应的载荷

        把响应打印到控制台上,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        先把响应构造成字符串,再打印。这里 responsePacket.getData() 是得到响应的字节数组。

3、创建DatagramPacket三种不同的参数场景

        如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        第一种:服务器接收客户端发来的请求,所以要存放在空白数组中。

        第二种:服务器构造好响应,返回给客户端的。

        第三种:客户端构造好请求,发送给服务器的。

4、执行代码

        启动服务器和启动客户端,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        客户端分别输入 hello 和 world,如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        服务器这边的显示:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        我们结束客户端程序,在执行客户端程序,不动服务器,输入你好,如图:

        客户端:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        服务器:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

        可以看到,客户端的端口号变了,因为终止了上一次的客户端程序,又重新执行客户端程序,系统会随机分配一个空闲端口给客户端使用,所以是不一样的。

5、客户端和服务器交互的过程

        过程如图:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言

下面是画图解释其中的过程:

网络编程套接字(3)——Java数据报套接字(UDP协议),网络,java,开发语言文章来源地址https://www.toymoban.com/news/detail-838952.html


都看到这了,点个赞再走吧,谢谢谢谢谢

到了这里,关于网络编程套接字(3)——Java数据报套接字(UDP协议)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • TCP/IP网络编程(二) 套接字协议及其数据传输特性

    关于协议 如果相隔比较远的两人进行通话,必须先决定通话方式,如果一方选择电话,另一方也必须选择电话,否则接受不到消息。 总之,协议就是为了完成数据交换而定好的约定。 创建套接字 协议族 通过socket函数的第一个参数传递套接字中使用的协议分类信息,此协议

    2024年02月10日
    浏览(41)
  • 【Java】网络编程与Socket套接字、UDP编程和TCP编程实现客户端和服务端通信

    为什么需要网络编程? 现在网络普及程序越来越高,网络上保存着我们日常生活中需要的各种资源,使用程序通过网络来获取这些资源的过程就需要网络编程来实现。 什么是网络编程? 网络编程,指网络上的主机,通过不同的进程以程序的方式实现网络通信(网络数据传输)

    2024年02月17日
    浏览(48)
  • Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显

    我们软件工作者,着重编写的是应用层的代码,但是发送这个数据,我们就需要将应用层传输到传输层,也就意味着我们需要调用应用层的API,统称为 Socket API。 套接字的分类: 流套接字:使用传输层TCP协议 特点: 有连接:使用 TCP 通信的双方,需要时刻保存对方的相关消

    2024年02月09日
    浏览(38)
  • 【网络】网络编程套接字

    目录 一、预备知识 1、网络通信理解 2、源IP地址和目的IP地址 3、端口号 二、网络字节序 三、socket编程接口 1、socket常见API 2、sockaddr结构 3、sockaddr结构体 3.1、sockaddr结构体 3.2、sockaddr_in结构体 四、简单的UDP网络程序 1、创建套接字接口 2、绑定端口号 3、服务器运行 4、创建

    2024年02月14日
    浏览(27)
  • 【网络编程】网络编程套接字(一)

    端口号(port)是传输层协议的内容. 端口号是一个2字节16位的整数; 端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理; IP地址 + 端口号能够标识网络上的某一台主机的某一个进程; 一个端口号只能被一个进程占用. 既然端口号是用来标识一个进程,

    2024年02月12日
    浏览(25)
  • 网络编程2(套接字编程)

    套接字编程:如何编写一个网络通信程序 1.网络通信的数据中都会包含一个完整的五元组: sip,sport,dip,dport,protocol(源IP,源端口,对端IP,对端端口,协议) 五元组完整的描述了数据从哪来,到哪去,用什么数据格式 2.网络通信–两个主机进程之间的通信:客户端服务

    2023年04月09日
    浏览(29)
  • 【网络】网络编程套接字(一)

    在前面我们说过可以使用IP地址来标识一台主机,但是我们光有IP地址就可以完成通信了嘛? 答案是:不可以,当我们的主机接收到了数据以后还要确定这个数据是发送给哪一个进程的,两台主机的两个软件进行网络通信时,我们还需要有一个其他的标识来区分出这个数据要给

    2024年02月06日
    浏览(26)
  • 【JavaEE】网络编程之TCP套接字、UDP套接字

    目录 1.网络编程的基本概念 1.1为什么需要网络编程  1.2服务端与用户端 1.3网络编程五元组  1.4套接字的概念 2.UDP套接字编程 2.1UDP套接字的特点  2.2UDP套接字API 2.2.1DatagramSocket类 2.2.2DatagramPacket类  2.2.3基于UDP的回显程序 2.2.4基于UDP的单词查询  3.TCP套接字编程 3.1TCP套接字的特

    2023年04月20日
    浏览(46)
  • 【JaveEE】网络编程之TCP套接字、UDP套接字

    目录 1.网络编程的基本概念 1.1为什么需要网络编程  1.2服务端与用户端 1.3网络编程五元组  1.4套接字的概念 2.UDP套接字编程 2.1UDP套接字的特点  2.2UDP套接字API 2.2.1DatagramSocket类 2.2.2DatagramPacket类  2.2.3基于UDP的回显程序 2.2.4基于UDP的单词查询  3.TCP套接字编程 3.1TCP套接字的特

    2023年04月13日
    浏览(44)
  • 【Linux网络编程】网络编程套接字二

    喜欢的点赞,收藏,关注一下把! TCP和UDP在编程接口上是非常像的,前面我们说过TCP是面向连接的,UDP我们上篇博客也写过了,我们发现UDP服务端客户端写好启动直接就发消息了没有建立连接。TCP是建立连接的,注定在写的时候肯定有写不一样的地方。具体怎么不一样,我们

    2024年04月15日
    浏览(39)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包