Java-Java基础学习(2)-网络编程-TCP-UDP

本文详细介绍了Java网络编程中的TCP和UDP通信协议,包括它们的特性、应用场景以及使用TCP和UDP进行文件上传的示例。同时展示了多线程实现的UDP聊天室,突出TCP的连接性与可靠性和UDP的实时性与轻量级特性。
摘要由CSDN通过智能技术生成

2.网络编程

2.1. 通信协议

  1. TCP、UDP对比

    • TCP 打电话

      • 连接,稳定

      • 三次握手,四次挥手

        三次握手
        A: 你瞅啥?
        B: 瞅你咋地?
        A:干一场!
        
        四次挥手
        A:我要走了
        B: 你真的要走了吗?
        B:你真的真的要走了吗?
        A:我真的要走了
        
        
      • 客户端、服务端

      • 传输完成,释放连接,效率低

    • UDP 发短信

      • 不连接,不稳定
      • 客户端,服务端,没有明确的界限
      • 不管有没有准备好,都可以发给你
      • 导弹
      • DDOS:洪水供给!(饱和攻击)

2.2. Tcp上传测试

1TcpUploadClient.java
    package com.hzs.basic.inet;

import java.io.*;
import java.net.Inet4Address;
import java.net.Socket;
import java.net.URL;
import java.net.UnknownHostException;

/**
 * @author Cherist Huan
 * @version 1.0
 * @date 2021/6/8 11:39
 * @note 文件上传客户端
 */
public class TcpUploadClient {
    public static void main(String[] args) throws IOException {
        // 1、创建一个Socket连接
        Socket socket = new Socket(Inet4Address.getByName("127.0.0.1"),9999);

        // 2、创建一个输出流
        OutputStream os = socket.getOutputStream();

        // 3、读取文件
       // FileInputStream fis = new FileInputStream(new File(String.valueOf(TcpUploadClient.class.getResource("6.jpg"))));
    //    URL resource = TcpUploadClient.class.getResource("/images/6.jpg");
    //    FileInputStream fis = new FileInputStream(resource.getPath());

        File file = new File("java-test-questions-06/src/main/resources/images/6.jpg");
       // File file = new File("images/6.jpg");
        System.out.println(file.getAbsolutePath());
        FileInputStream fis = new FileInputStream(file);

        // 4、写出文件
        byte[] buffer = new byte[1024];
        int len;
        while((len = fis.read(buffer))!= -1)
        {
            os.write(buffer,0,len);
        }


        // 通知服务器,我已经传输完毕了
        socket.shutdownOutput(); // 我已经传输完毕

        // 接受服务器的响应,确定服务器接受完毕,才能关闭连接
        InputStream is2 = socket.getInputStream();
        byte[] buffer2 = new byte[1024];
        int len2;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();


        while((len2 = is2.read(buffer2))!= -1)
        {
         baos.write(buffer2,0,len2);
        }

        System.out.println(baos.toString());

        // 5、关闭资源
        baos.close();

        fis.close();
        os.close();
        socket.close();
    }
}

    
2TcpUploadServer.java
    package com.hzs.basic.inet;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;

/**
 * @author Cherist Huan
 * @version 1.0
 * @date 2021/6/8 11:39
 *  @note 文件上传服务端
 */
public class TcpUploadServer {
    public static void main(String[] args) throws IOException {

        // 1、创建ServerSocket
        ServerSocket serverSocket = new ServerSocket(9999);

        // 2、创建Socket监听
        Socket socket = serverSocket.accept();

        // 3、获取输入流
        InputStream is = socket.getInputStream();

        // 4、文件输出

//        URL resource = TcpUploadClient.class.getResource("/images/6_receive.jpg");
//        //FileOutputStream fos = new FileOutputStream(new File(resource.getPath()));
//        FileOutputStream fos = new FileOutputStream(resource.getPath());

        File file = new File("java-test-questions-06/src/main/resources/images/6receive.jpg");
        //File file = new File("images/6_receive.jpg");
        FileOutputStream fos = new FileOutputStream(file);

        byte[] buffer;
        buffer = new byte[1024];
        int len;

        while((len = is.read(buffer))!= -1)
        {
            fos.write(buffer,0,len);
        }


        // 通知客户端,我已经接受完毕
        OutputStream os = socket.getOutputStream();
        os.write("服务端返回,服务端已经接受完毕了".getBytes());

        // 5、关闭资源
        os.close();

        fos.close();
        is.close();
        socket.close();
        serverSocket.close();

    }
}

    

总结:

  • 客户端

    1. 建立socket连接
    2. 创建一个输出管道流
    3. 读取需要上传的文件
    4. 将文件写出到管道流
    5. 通知服务器,我已经传输完毕
    6. 接受服务器的响应,确定服务器接受完毕,才能关闭连接
    7. 关闭资源
  • 服务端

    1. 建立ServerSocker端口服务
    2. 创建Socket监听,返回Socket
    3. 获取输入流
    4. 获取输入流中文件输出
    5. 通知客户端,我已经接受完毕
    6. 关闭资源

2.3. Udp 传输

1UdpClient.java
    
package com.hzs.basic.inet;

import java.io.IOException;
import java.net.*;

/**
 * @Author Cherist Huan
 * @Date 2021/6/10 10:41
 * @Version 1.0
 */
public class UdpClient {
    public static void main(String[] args) throws IOException {

        // System.out.println(("AB".getBytes()).length);//2

        // 1、建立一个Socket
        DatagramSocket socket = new DatagramSocket();

        // 2、建包
        String msg = "Hello Cherist Huan!";
        InetAddress byName = Inet4Address.getByName("127.0.0.1");
        int port = 9090;
        DatagramPacket datagramPacket = new DatagramPacket(msg.getBytes(),0,msg.getBytes().length,byName,port);

        // 3、发送包
        socket.send(datagramPacket);
        // 4、关闭流
       socket.close();
    }
}

2UdpServer.java
    package com.hzs.basic.inet;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * @Author Cherist Huan
 * @Date 2021/6/10 10:57
 * @Version 1.0
 */
public class UdpServer {
    public static void main(String[] args) throws IOException {
        // 1、开放端口
        DatagramSocket datagramSocket = new DatagramSocket(9090);

        // 2、接受数据包
        byte[] buffer = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);

        datagramSocket.receive(packet);// 阻塞式接受
        System.out.println(new String(packet.getData(),0,packet.getLength()));
        // 关闭流
        datagramSocket.close();
    }
}

    

2.4. Udp聊天室(多线程)

1TalkSend.java
package com.hzs.basic.inet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

/**
 * @Author Cherist Huan
 * @Date 2021/6/10 15:24
 * @Version 1.0
 */
public class TalkSend implements  Runnable {

    DatagramSocket socket = null;
    BufferedReader reader = null;

    private  int fromPort;
    private  int toPort;
    private  String toIp;

    public TalkSend(int fromPort, int toPort, String toIp) {
        this.fromPort = fromPort;
        this.toPort = toPort;
        this.toIp = toIp;

        try {
            socket = new DatagramSocket(fromPort);
            reader = new BufferedReader(new InputStreamReader(System.in));

        } catch (SocketException e) {
            e.printStackTrace();
        }

    }

    public void run() {
          while(true)
          {
              try {
                  String data = reader.readLine();
                  byte[] dataBytes = data.getBytes();

                  DatagramPacket packet = new DatagramPacket(dataBytes,0,dataBytes.length,new InetSocketAddress(this.toIp,this.toPort));

                  socket.send(packet);

                  if(data.equals("bye")){
                      break;
                  }

              } catch (IOException e) {
                  e.printStackTrace();
              }
          }

          socket.close();
    }
}

2TalkReceive.java
package com.hzs.basic.inet;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * @Author Cherist Huan
 * @Date 2021/6/10 15:44
 * @Version 1.0
 */
public class TalkReceive  implements  Runnable{

    DatagramSocket socket = null;
    private int port;
    private  String msg;
    public  TalkReceive(int port,String msg){
        this.port = port;
        this.msg = msg;
        try {
            socket = new DatagramSocket(port);

        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    public void run() {
       while(true){

           try {
               byte[] container = new byte[1024];
               DatagramPacket packet = new DatagramPacket(container, 0, container.length);

               socket.receive(packet);//阻塞式接受包裹

               // 断开连接 bye
               byte[] data = packet.getData();
               String receiveData = new String(data,0,data.length);
               System.out.println(msg+":"+receiveData);

               if(receiveData.equals("bye"))
               {
                   break;
               }

           } catch (IOException e) {
               e.printStackTrace();
           }
       }
       socket.close();
    }
}


3TalkStudent.java
package com.hzs.basic.inet;

/**
 * @Author Cherist Huan
 * @Date 2021/6/10 15:56
 * @Version 1.0
 */
public class TalkStudent {
    public static void main(String[] args) {
        // 开启两个线程
        new Thread(
                new TalkSend(7777,9999,"localhost")
        ).start();

        //学生端接受线程端口(服务端口 8888)
        new Thread(
                new TalkReceive(8888,"老师说")
        ).start();
    }
}

4TalkTeacher.java
package com.hzs.basic.inet;

/**
 * @Author Cherist Huan
 * @Date 2021/6/10 16:04
 * @Version 1.0
 */
public class TalkTeacher {
    public static void main(String[] args) {
        // 开启两个线程
        new Thread(
                new TalkSend(6666,8888,"localhost")
        ).start();

        //老师端接受线程端口(服务端口 9999)
        new Thread(
                new TalkReceive(9999,"学生说")
        ).start();
    }
}    

2.5 对比总结

Java网络编程中,TCP(传输控制协议)和UDP(用户数据报协议)是两种主要的传输层协议。它们各有特点和适用场景。

TCP传输

特点

  1. 面向连接:TCP在传输数据之前需要先建立连接,传输完成后需要断开连接。
  2. 可靠传输:TCP通过序列号、确认应答、超时重传等机制确保数据的可靠传输。
  3. 流量控制:TCP通过滑动窗口机制进行流量控制,避免发送方发送速率过快导致接收方处理不过来。
  4. 拥塞控制:TCP通过慢开始、拥塞避免、快重传、快恢复等算法进行拥塞控制,避免网络拥塞。

应用场景

  • 需要可靠传输的应用,如文件传输、电子邮件等。
  • 对数据传输顺序有要求的应用,如网页浏览、在线视频等。

UDP传输

特点

  1. 无连接:UDP在传输数据之前不需要建立连接,每个数据报都是一个独立的信息。
  2. 不可靠传输:UDP不保证数据的可靠传输,不进行流量控制和拥塞控制。
  3. 开销小:由于UDP协议简单,传输开销小,适合实时性要求高的应用。

应用场景

  • 实时性要求高的应用,如音频、视频流等。
  • 允许一定程度上数据丢失的应用,如实时游戏、实时股市行情等。
  • 21
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JasonHuan1123

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值