网络编程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、通信流程

相关推荐
智慧物业老杨30 分钟前
物业日常巡查的数智化重构:从“打卡式巡检“到“闭环式风控“
android·java·人工智能·系统架构·rxjava
步行cgn7 小时前
Spring c 命名空间注入详解
java·后端·spring
明月_清风7 小时前
Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理
java·后端·maven
比兔代理8 小时前
正向代理与反向代理技术辨析,为什么代理 IP 属于正向代理
服务器·网络·http·ip
aramae8 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
Rain的Java大神之路8 小时前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
小贺儿开发8 小时前
Unity 家居视频遥控(细节优化)
科技·unity·程序员·udp·视频·工具·通信
Wang's Blog9 小时前
Java 接入Redis: 通用命令与键管理
java·服务器·redis
Wang's Blog9 小时前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis
Ivanqhz9 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络