网络编程2----UDP简单客户端服务器的实现

首先我们要知道传输层提供的协议主要有两种,TCP协议和UDP协议,先来介绍一下它们的区别:

1、TCP是面向连接的,UDP是无连接的。

连接的本质是双方分别保存了对方的关键信息,而面向连接并不意味着数据一定能正常传输到对方电脑中,只是说在遇到问题时会采取一些办法重新传输这个数据,而无连接意味着一方只需要发送数据即可,不需要提前取得对方的同意,至于这个数据发出去之后怎么样了它不会关心。

2、TCP是可靠传输的,UDP是不可靠传输的

可靠传输其实就是第一点说的,A主机知道B主机有没有收到自己发送的消息,在发送失败时,会采取一定的措施(尝试重传之类的),但是并不代表这个消息能100%送达。

可靠传输需要付出什么代价:

1、机制更复杂

2、传输效率会降低

3、TCP是面向字节流的,UDP是面向数据报的

此处说的字节流和文件说的字节流是一个意思,TCP是以字节为单位进行数据传输,而UDP是通过数据报为单位进行数据传输

4、TCP和UDP都是全双工的

全双工的意思是双方都既可以发送数据,也可以接收数据,数据的流动不是单向的。

接下来,我们来编写一个简单的UDP客户端/服务器通信的程序,这里的服务器我们采用回显服务器(echo server),不执行复杂的逻辑,客户端发送什么,服务器就会原封不动的返回什么。

客户端的代码:

复制代码
UdpEchoClient

package network;

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

public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIp = "";
    private int serverport = 0;

    public UdpEchoClient(String ip,int port) throws SocketException {
        socket = new DatagramSocket();
        serverIp = ip;
        serverport = port;
    }

    public void start() throws IOException {
        System.out.println("客户端启动!");
        Scanner scanner = new Scanner(System.in);
        while(true){
            //1、从客户端读取要发送的数据
            System.out.println("请输入你想发送的内容");
            String request = scanner.next();
            //2、把要发送的数据转换成DatagramPacket类型的对象,发给服务器
            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 client = new UdpEchoClient("127.0.0.1",9090);
        client.start();
    }
}

服务器的代码:

复制代码
UdpEchoServer

package network;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UdpEchoServer {
    private DatagramSocket socket = null;

    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
        //这么做就是手动指定端口
        //socket = new DatagramSocket();
        //这么做就是系统自动指定端口
    }

    //使用这个方法启动服务器
    public void start() throws IOException {
        System.out.println("服务器启动");
        while(true){
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            //1、服务器接收到来自客户端的消息并且将内容放在输出型参数datagramPacket中
            String request = new String(requestPacket.getData(),0, requestPacket.getLength());
            //将二进制形式的datagramPacket数据变为字符串类型的数据
            //2、根据请求计算响应(大部分服务器都会经历这个步骤)
            String response = process(request);
            //把响应返回客户端,通过send发送信息
            DatagramPacket reponsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(reponsePacket);
            //4、打印一个日志,输出这次数据交互的详情
            System.out.printf("[%s:%d] req=%s, resp=%s\n", requestPacket.getAddress().toString(),
                    requestPacket.getPort(), request, response);
        }
    }

    private String process(String request) {
        return request;
        //此处编写一个回显服务器,客户端发来什么,服务器就返回什么
    }

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

运行截图:

代码的几个重点:

1、可以看到DatagramPacker的构造方法有三种:

  • 只指定字符数据缓冲区的(客户端收响应的时候要用,服务器收请求的时候也要用)
  • 指定字符数组缓冲区,同时只能一个InetAddress对象(这个对象同时包含了IP和端口)(服务器返回响应给客户端)
  • 指定字符数组缓冲区,同时指定IP+端口号

其实都是让它们在发送数据的时候不仅要指定数据的内容,同时和指定这个数据要发送到的地址。

2、通信流程

相关推荐
Moe4883 分钟前
合并Pdf、excel、图片、word为单个Pdf文件的工具类(拿来即用版)
java·后端
oliveira-time13 分钟前
原型模式中的深浅拷贝
java·开发语言·原型模式
进阶的猿猴37 分钟前
easyExcel实现单元格合并
java·excel
listhi5201 小时前
使用SCP命令在CentOS 7上向目标服务器传输文件
linux·服务器·centos
小许学java1 小时前
MySQL-触发器
java·数据库·mysql·存储过程·触发器
JEECG低代码平台1 小时前
【2025/11】GitHub本月热度排名前十的开源Java项目
java·开源·github
百***86051 小时前
Spring BOOT 启动参数
java·spring boot·后端
Jason_Orton1 小时前
笔记本电脑触摸板失灵另类解决办法(I2C HID设备黄色感叹号)
运维·服务器·计算机网络·网络安全·电脑
跟着珅聪学java1 小时前
Spring Boot 中整合 MySQL 并打印 SQL 日志
java·spring boot
ᐇ9591 小时前
Java集合框架实战:HashMap与HashSet的妙用
java·开发语言