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

相关推荐
这孩子叫逆6 分钟前
Spring Boot项目的创建与使用
java·spring boot·后端
星星法术嗲人9 分钟前
【Java】—— 集合框架:Collections工具类的使用
java·开发语言
一丝晨光28 分钟前
C++、Ruby和JavaScript
java·开发语言·javascript·c++·python·c·ruby
C++忠实粉丝29 分钟前
Linux环境基础开发工具使用(2)
linux·运维·服务器
天上掉下来个程小白30 分钟前
Stream流的中间方法
java·开发语言·windows
xujinwei_gingko41 分钟前
JAVA基础面试题汇总(持续更新)
java·开发语言
liuyang-neu43 分钟前
力扣 简单 110.平衡二叉树
java·算法·leetcode·深度优先
康熙38bdc1 小时前
Linux 环境变量
linux·运维·服务器
一丝晨光1 小时前
Java、PHP、ASP、JSP、Kotlin、.NET、Go
java·kotlin·go·php·.net·jsp·asp
l1x1n01 小时前
网络安全概述:从认知到实践
网络