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

相关推荐
我言秋日胜春朝★3 分钟前
【Linux】进程地址空间
linux·运维·服务器
爪哇学长7 分钟前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
ExiFengs11 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
paj12345678913 分钟前
JDK1.8新增特性
java·开发语言
繁依Fanyi24 分钟前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
C-cat.24 分钟前
Linux|环境变量
linux·运维·服务器
慧都小妮子35 分钟前
Spire.PDF for .NET【页面设置】演示:打开 PDF 时自动显示书签或缩略图
java·pdf·.net
m512739 分钟前
LinuxC语言
java·服务器·前端
IU宝44 分钟前
C/C++内存管理
java·c语言·c++
瓜牛_gn44 分钟前
依赖注入注解
java·后端·spring