UDP网络传输

目录

🌹socket

🍃UDP数据报

🍃DatagramPacket API

🍃 DatagramSocket API

🌹 UDP回显服务器

🍃服务器端

🍃客户端


socket

我们将socket的api分为两组,一组是基于TCP的api,一组是基于UDP的api。

其中基于UDP的api的特点:无连接,不可靠传输,面向数据报,全双工

基于TCP的api的特点:有连接,可靠传输,面向字节流,全双工

        理解有无连接,我们可以想一下打电话和发短信,打电话的信息传输就可以认为是有连接的传输,双方通话需要一方申请连接,一方同意建立连接后才能进行通话。如果有一方拒绝连接那么信息传输就无法完成。而发短信则不需要建立这样的连接,只需要发送方将短信发给接收方即可,接收并没有提前得知,也无法拒绝。

       理解可不可靠传输,这里的可靠或者不可靠并不是绝对的可不可靠,可靠意思是会尽力进行传输,尽可能的将信息传过去,有一系列的帮助传输的策略。即使传输失败也是知道失败了。而不可靠传输则是将信息传输过去就不管了,至于有没有传输成功,并不会关心,也不会知道结果。

        面向数据包则是说传输数据以一个UDP数据包为基本单位。我们可以使用Scanner来进行数据的读和写操作。

        面向字节流就是以字节为传输单位进行读和写。读写操作更灵活。

        全双工则是双方通信一条路径。

UDP数据报

 一般一个数据报由两部分组成,包含数据包的报头和载荷

        UDP的包头一共8个字节,包含4个部分:源端口,目的端口,数据报长度,校验和。每个部分各占2个字节。可以知道表示数据报的长度的信息也是只有两个字节,两个字节的范围(0~65535),显然也就制约了一个UDP数据报的大小最多为64k左右

载荷就是上层协议的报文,每层的数据报经过封装到下一层后就变成下层协议数据报的载荷。

DatagramPacket API

 DatagramSocket API

 UDP回显服务器

服务器端

public class UdpEchoSeverse {
    private DatagramSocket datagramSocket = null;
    public UdpEchoSeverse(int pose) throws SocketException {
        //服务器的socket构造方法需要输入一个端口号,相当于某个餐厅的10号窗口
        //要让客户端(顾客)知道窗口位置
        datagramSocket = new DatagramSocket(pose);
    }
    public void start() throws IOException {
        System.out.println("服务器启动");

        //while来循环接受客户端发来的请求,来处理
        while (true) {
            //这里创建了一个空的packet,相当于一个空包裹,用来接受客户端发来的请求
            DatagramPacket requestPacket = new DatagramPacket(new byte[4090], 4090);

            //receive是一个返回值是参数的方法,参数里写的是上面创建好的空的packet,通过调用receive方法后返回一个有客户端请求的packet
            datagramSocket.receive(requestPacket);

            //这里将datagrampacket转成String只是为了方便对客户端的请求进行计算(process)
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());
            String response = process(request);

            //将经过process处理后的packet再次封装成新的responsepacket(包裹),准备接下来将相应发送给客户端
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());

            //发送响应
            datagramSocket.send(responsePacket);

            //打印日志:
            System.out.println("["+requestPacket.getAddress()+","+requestPacket.getPort()+"]"+","+"req:"
            +request+"rep:"+response);
        }
    }
    //process方法是为了处理客户端请求的,是服务器中的关键方法,由于这个程序至少最简单的回显服务器,所以这里直接return了
    public String process(String request) {
          return  request;
    }

    public static void main(String[] args) throws IOException {
        //必须有main方法才能运行,输入端口号
        UdpEchoSeverse udpEchoSeverse = new UdpEchoSeverse(6060);
        udpEchoSeverse.start();
    }
}

客户端

public class UdpEchoClient {
    private DatagramSocket datagramSocket = null;
    //severIp和severpose分别指的是服务器的ip和端口号,要给服务器发送请求就必须知道对应服务器的ip和端口号
    //就相当于买东西要知道商店的位置
    private String severIp;
    private int severpose;

    //构造方法,不需要知道客户端socket的端口号,至于传服务器的ip和端口号
    //不需要传客户端的端口号不是意味着客户端没有端口号,而是让系统自动分配一个空闲的端口号给客户端,相当于餐厅的座位,那里没人坐哪里就行
    public UdpEchoClient(String severIp,int severpose) throws SocketException {
        datagramSocket = new DatagramSocket();
        this.severIp = severIp;
        this.severpose = severpose;
    }
    public void start() throws IOException {
        System.out.println("客户端启动");

        //同理,循环发送请求
        while (true){
            //udp是以一个udp数据包为单位的读与写
            //可以直接通过scanner来输入请求
            Scanner scanner = new Scanner(System.in);
            String request = scanner.next();
            //将输入的请求打包成requestpacket,来进行发送
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(severIp),
                    severpose);

            //发送请求
            datagramSocket.send(requestPacket);

            //准备一个空的packet来接收服务器发过来的响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4090],4090);
            datagramSocket.receive(responsePacket);

            //转成字符串方便打印
            String response = new String(responsePacket.getData(),0,responsePacket.getLength());
            System.out.printf("req:%s,res:%s\n",request,response);
        }
    }

    public static void main(String[] args) throws IOException {
        //写的是服务器的ip和端口号
        UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1",6060);
        udpEchoClient.start();
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值