传输层中UDP的深入理解以及socket中UDP的使用

目录

一.学习UDP的预备知识

1.熟悉网络通信中的五元组

(1)源IP地址和目的IP地址

(2)源端口号和目的端口号

(3)协议号

2.什么是客户端和服务端

二.socketAPI中UDP的使用

1.UDP在socket中使用的类和方法

2.使用DatagramSocket类实现一个简单的单词翻译程序(包含客户端和服务端)

(1)图示 

(2)代码实现

(3)运行结果

三.UDP协议详情 

1.UDP的协议端格式

 2.UDP的特点

3.了解基于UDP的一些应用层协议


一.学习UDP的预备知识

1.熟悉网络通信中的五元组

(1)源IP地址和目的IP地址

确定发送消息的主机和接收消息的主机。

(2)源端口号和目的端口号

确定是该主机的哪个进程发送的消息和接收消息主机中的哪个进程。

端口号的划分:0~1023为知名端口号,有HTTP(80端口),HTTPS(443端口),FTP(21端口),SSH(22端口)等应用层协议。我们自己写程序时要避免知名端口号,以免发生异常。

1024~65535:操作系统动态分配的端口号,其中客户端的就是由操作系统从这个范围进行分配的。

其中一个进程可以绑定多个端口号,一个端口号不能被多个进程绑定

(3)协议号

发送消息的进程和接收的进程之间遵守的协议。

2.什么是客户端和服务端

二.socketAPI中UDP的使用

1.UDP在socket中使用的类和方法

其中使用到的类为DatagramSocket。常用的方法如下:

方法名方法说明
DatagramSocket(int port,InetAddress laddr) 创建一个数据报套接字,绑定到指定的本地地址
DatagramSocket(SocketAddress bindaddr)创建一个数据报套接字,绑定到指定的本地套接字地址
void bind(SocketAddress addr)将此DatagramSocket绑定到特定的地址和端口
void connect(InetAddress address, int port)
 将套接字连接到此套接字的远程地址
void receive(DatagramPacket p)从此套接字接收数据报包
void close()
 关闭此数据报套接字
void send(DatagramPacket p)
 从此套接字发送数据报包

在使用DatagramSocker中的数据是以数据报为单位进行发送的。

使用该类来进行发送数据报,这里使用到了以下两个构造器。

2.使用DatagramSocket类实现一个简单的单词翻译程序(包含客户端和服务端)

(1)图示 

(2)代码实现

客户端:

这里还用到InetAddress 类下的一个静态方法

package javaweb.udptcp2.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;

public class UDPClient {
    DatagramSocket socket = null;
    String serverIp = null;
    int serverPort;
    //客户端的端口号不需要进行绑定,由系统自动分配
    public UDPClient(String serverIp, int serverPort) throws SocketException {
        socket = new DatagramSocket();
        this.serverIp = serverIp;
        this.serverPort = serverPort;
    }
    //启动客户端(这里使用循环可以一直输入请求)
    public void start() throws IOException {
        System.out.println("客户端启动");
        //使用scanner来输入请求
        Scanner sc = new Scanner(System.in);
        while (true) {
            String request = sc.nextLine();
            //退出客户端
            if("exit".equals(request)) {
                break;
            }
            //构造要发送的数据报(这里将字符串数据转化为二进制来进行发送)
            //InetAddres.getName()是确定主机名称的IP地址
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(serverIp), serverPort);
            //将构造好的数据报发送给指定的客户端
            socket.send(requestPacket);

            //以数据报的形式接收服务端的请求
            DatagramPacket responPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responPacket);
            //将接收到的消息转化为字符串(使用trim是去除字符串的前后空格)
            String respons = new String(responPacket.getData(),0,responPacket.getLength()).trim();

            //将得到的响应打印到控制台上
            System.out.println(respons);
        }
    }
    //启动客户端
    public static void main(String[] args) throws IOException {
        //这里的ip是本机的回环ip
        UDPClient client = new UDPClient("127.0.0.1",9090);
        client.start();
    }
}

服务端:

package javaweb.udptcp2.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;

//实现一个简单的英文翻译的服务端
public class UDPServer {
    DatagramSocket socket = null;
    //保存单词
    Map<String, String> words = new HashMap<>();
    //给服务端需要绑定端口号
    public UDPServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
        words.put("猫","cat");
        words.put("狗","dog");
        words.put("鱼","fish");
    }
    //启动服务端
    public void start() throws IOException {
        System.out.println("服务端已经启动");
        while (true) {
            //接收客户端发来的请求
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            String request = new String(requestPacket.getData(),0,requestPacket.getLength()).trim();

            //根据请求构造响应
            String respons = process(request);

            //将响应数据发送给客户端
            DatagramPacket responsPacket = new DatagramPacket(respons.getBytes(),respons.getBytes().length,requestPacket.getSocketAddress());
            socket.send(responsPacket);

            //将服务端端发送给哪个客户端的数据输出到控制台上
            System.out.printf("[%s:%d]; request:%s  respons:%s\n",requestPacket.getAddress().toString()
                            ,requestPacket.getPort(), request, respons);
        }
    }
    //计算出的响应
    private String process(String request) {
        if(words.containsKey(request)) {
            return words.get(request);
        } else {
            return "未找到";
        }
    }
    //启动服务端
    public static void main(String[] args) throws IOException {
        UDPServer server = new UDPServer(9090);
        server.start();
    }
}

注意:这里数据报中的缓冲区是自己设置大小的,如果发送的数据超过缓冲区的大小则会自动截断,所以这里的大小需要自己配置。

(3)运行结果

三.UDP协议详情 

1.UDP的协议端格式

 协议格式详解图:

 2.UDP的特点

  1. 无连接:知道对端的IP和端口号就直接进行传输, 不需要建立连接。
  2. 不可靠:没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息。
  3. 面向数据报:不能够灵活的控制读写数据的次数和数量。对于UDP传输,发送端如果发送了100字节的数据,那么接收端必须也一次接受100字节的数据,不能分开进行接收。
  4. 只有接收缓冲区没有发送缓冲区(发送缓冲区主要用于超时重传)。
  5. 大小受限,UDP所能传输数据的最大长度为64K。

3.了解基于UDP的一些应用层协议

  • NFS: 网络文件系统
  • TFTP: 简单文件传输协议
  • DHCP: 动态主机配置协议
  • BOOTP: 启动协议(用于无盘设备启动)
  • DNS: 域名解析协议
     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值