Java偶像练习生,出道未半而中道崩殂头像
从Socket到UDP回显服务器:Java网络编程完整指南封面图

从Socket到UDP回显服务器:Java网络编程完整指南

从Socket到UDP回显服务器:Java网络编程完整指南

摘要:本文讲解 UDP 协议与 Java 数据报套接字编程:Socket 概念与分类、UDP 四大特点、DatagramSocket 与 DatagramPacket 核心 API,并完整实现一个 UDP 回显服务器与客户端。

目录

1.socket套接字

2.UDP协议的特点

3.UDP数据报套接字编程

4.基于UDP实现一个回显服务器

正文

1.socket套接字

Socket(套接字)是操作系统提供给应用程序的一组网络编程接口,它把「传输层协议 + IP 地址 + 端口号」抽象成一个可读写的文件描述符,让程序可以像读写文件一样收发网络数据。

1.1分类

Socket套接字主要针对传输层协议划分为如下三类:

  • 1.流套接字:使用传输层TCP协议.
  • 2.数据报套接字:使用传输层UDP协议.
  • 3.原始套接字:使用传输层自定义协议.
    这篇文章我们展开学习数据报套接字:使用传输层UDP协议.

2.UDP协议的特点

UDP协议,即User Datagram Protocol(用户数据报协议),传输层协议.

  • **1.无连接:**对UDP来说,UDP协议本身不保存对方的信息,就是无连接.
  • **2.不可靠传输:**只是把数据发送了就不管了.
  • **3.面向数据报:**读取数据的时候以一个数据报为单位.
  • **4.全双工:**通信链路支持双向通信.(可写可读)

3.UDP数据报套接字编程

3.1API介绍

DatagramSocket
DatagramSocket是UDP Socket,用于发送和接受数据报.
DatagramSocket构造方法:
在这里插入图片描述
DatagramSocket方法:
在这里插入图片描述

3.2DatagramPacket

DatagramPacket是UDP Socket发送和接受的数据报,表示一个完整的数据报.
DatagramPacket构造方法:
在这里插入图片描述

Datagrampacket方法:

在这里插入图片描述
==注意:==构造UDP发送的数据报时,需要传入SocketAddress.

4.基于UDP实现一个回显服务器

基于上述内容,我们来实现一个回显服务器.
首先我们先了解一般服务器的工作流程:

  • 客户端向服务器发起请求,服务器根据客户端请求返回响应结果.例如,我在浏览器搜索关键词"服务器图片’',点击搜索就会呈现一些结果给我们.这就是响应.
  • 回显服务器比较一般的服务器比较特殊的是:它不做任何业务处理,收到什么就原样返回什么.一般服务器需要根据请求内容去查数据库、算逻辑、拼页面,而回显服务器的"计算响应"这一步可以省略,直接把请求当作响应发回去.正因为逻辑极简,它常被用来验证网络连通性、测试客户端收发流程是否正确.
    客户端发送请求时,数据报的源地址是客户端 ip + 客户端端口,目的地址是服务器 ip + 服务器端口。服务器收到请求后,从数据报中取出源 ip 和源端口(即客户端地址),在构造响应时把它们作为目的 ip 和目的端口发回去。这正是 UDP 无连接、每个数据报都携带完整地址信息的体现。
    在这里插入图片描述
    服务器端代码:
package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

public class UdpEchoServer {
    //DatagramSocket负责收发数据
    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就是一个UDP数据报,此处此处构造一个空的缓冲区(大小为4096字节  ),用来保存UDP的载荷内容,此时这个数据报还是空的,什么都没有
            DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
            //经过receive代码行之后,requestPacket 中会被填入请求的数据包信息,此时的数据包已经有数据:有源IP,源端口号,载荷
            socket.receive(requestPacket);
            //把读取到的二进制数据,转成字符串.
            String request=new String(requestPacket.getData(),0,requestPacket.getLength());

            //2.根据请求计算响应(但是此处是回显服务器,这个环节就省略了,请求是什么,响应就是什么)
            String response=process(request);
            //3把响应返回给客服端\
            //根据response构造DatagramPacket,发送给用户
            //此时客户端的ip,端口号变成了目的ip和目的端口号
            DatagramPacket responsePacket=new DatagramPacket(
                    response.getBytes(),
                    response.getBytes().length,
                    requestPacket.getSocketAddress()
            );

            socket.send(responsePacket);

            //4.打印日志
            System.out.printf("[%s:%d] req:%s,resp:%s\n",
                    requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);
        }
    }

    //后续需要只需写别的服务器,只需要修改这个地方即可
    public String process(String request) {

        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server=new UdpEchoServer(9090);//固定端口号,若此时此端口号已经被其他应用占用,就有可能导致程序启动失败
        server.start();
    }
}


客户端代码:

package network;

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UdpEchoClient {
    //socket是用来收发数据报的
    private DatagramSocket socket=null;

    //Udp本身不保存对端的信息(IP,端口号),自己的代码保存一下
    private String serverIp;
    private int serverPort;

    //和服务器不同,此处的构造方法需要指定访问的服务器的地址
    public UdpEchoClient(String serverIp,int serverPort) throws SocketException {
        this.serverIp=serverIp;
        this.serverPort= serverPort;
        socket=new DatagramSocket();
    }

    public void start() throws IOException {
        Scanner scanner=new Scanner(System.in);
        //1.从控制台中读取用户输入的内容
        while(true){
            System.out.println("请输入要发送的内容");
            if(!scanner.hasNext()){
                break;
            }
            String request= scanner.next();
            //2.把请求打包成一个数据包发送给服务器,需要构造DataGramPacket对象
            DatagramPacket requestPacket=new DatagramPacket(
                    request.getBytes(),
                    request.getBytes().length,
                    InetAddress.getByName(serverIp),
                    serverPort);
            //3.send方法发送数据
            socket.send(requestPacket);
            //4.接收服务器的响应
            //接收响应时要重新new一个数据包来存放,此处构造一个空的缓冲区(大小为4096字节)             包的大小
            DatagramPacket responsePacket=new DatagramPacket(new byte[4096],4096);
            //经过receive方法,responsePacket 中会被填入服务器返回的数据,responsePacket不再为空
            socket.receive(responsePacket);

            //5.对从服务器读取出来的数据进行解析,打印出来
            String response=new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.println(response);
        }
    }
    public static void main(String[] args) throws IOException {
        //127.0.0.1指代本机ip,9090端口号
        UdpEchoClient client=new UdpEchoClient("127.0.0.1",9090);
        client.start();
    }
}

运行结果展示:
在这里插入图片描述
在这里插入图片描述
本文结束~欢迎一起来交流技术!!!
在这里插入图片描述

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/2502_92960941/article/details/169557837

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--