【JavaSE】Java基础语法(四十五):TCP UDP 全解

简介: 1. TCP发送数据Java中的TCP通信Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。Java为客户端提供了Socket类,为服务器端提供了ServerSocket类

1. TCP发送数据

  • Java对基于TCP协议的的网络提供了良好的封装,使用Socket对象来代表两端的通信端口,并通过Socket产生IO流来进行网络通信。
  • Java为客户端提供了Socket类,为服务器端提供了ServerSocket类

ab66bd537e58482188832fb39bf9fcfa.png

相关方法

be32e43d27a04943b0960ef1fb46571d.png

  • 示例代码
public class ClientDemo {
  public static void main(String[] args) throws IOException {
    //创建客户端的Socket对象(Socket)
    //Socket(String host, int port) 创建流套接字并将其连接到指定主机上的指定端口号
    Socket s = new Socket("127.0.0.1",10000);
    //获取输出流,写数据
    //OutputStream getOutputStream() 返回此套接字的输出流
    OutputStream os = s.getOutputStream();
    os.write("hello,tcp,我来了".getBytes());
    //释放资源
    s.close();
  }
}

2. TCP接收数据【应用】

  • 构造方法: 创建绑定到指定端口的服务器套接字
ServletSocket(int port)


  • 相关方法:监听要连接到此的套接字并接受它
Socket accept()


注意事项


accept方法是阻塞的,作用就是等待客户端连接

客户端创建对象并连接服务器,此时是通过三次握手协议,保证跟服务器之间的连接

针对客户端来讲,是往外写的,所以是输出流

针对服务器来讲,是往里读的,所以是输入流

read方法也是阻塞的

客户端在关流的时候,还多了一个往服务器写结束标记的动作

最后一步断开连接,通过四次挥手协议保证连接终止

  • 三次握手
  • 四次挥手

3. TCP程序练习

案例需求

客户端:发送数据,接受服务器反馈

服务器:收到消息后给出反馈

案例分析

客户端创建对象,使用输出流输出数据

服务端创建对象,使用输入流接受数据

服务端使用输出流给出反馈数据

客户端使用输入流接受反馈数据

代码实现

// 客户端
public class ClientDemo {
  public static void main(String[] args) throws IOException {
    Socket socket = new Socket("127.0.0.1",10000);
    OutputStream os = socket.getOutputStream();
    os.write("hello".getBytes());
    // os.close();如果在这里关流,会导致整个socket都无法使用
    socket.shutdownOutput();//仅仅关闭输出流.并写一个结束标记,对socket没有任何
    影响
    BufferedReader br = new BufferedReader(new
    InputStreamReader(socket.getInputStream()));
    String line;
    while((line = br.readLine())!=null){
      System.out.println(line);
    }
    br.close();
    os.close();
    socket.close();
  }
}
// 服务器
public class ServerDemo {
  public static void main(String[] args) throws IOException {
    ServerSocket ss = new ServerSocket(10000);
    Socket accept = ss.accept();
    InputStream is = accept.getInputStream();
    int b;
    while((b = is.read())!=-1){
      System.out.println((char) b);
    }
    System.out.println("看看我执行了吗?");
    BufferedWriter bw = new BufferedWriter(new
    OutputStreamWriter(accept.getOutputStream()));
    bw.write("你谁啊?");
    bw.newLine();
    bw.flush();
    bw.close();
    is.close();
    accept.close();
    ss.close();
  }
}

4. TCP程序文件上传练习【应用】

案例需求

客户端:数据来自于本地文件,接收服务器反馈

服务器:接收到的数据写入本地文件,给出反馈

案例分析

- 创建客户端对象,创建输入流对象指向文件,每读一次数据就给服务器输出一次数据,输出

结束后使用shutdownOutput()方法告知服务端传输结束

- 创建服务器对象,创建输出流对象指向文件,每接受一次数据就使用输出流输出到文件中,

传输结束后。使用输出流给客户端反馈信息

- 客户端接受服务端的回馈信息

相关方法

6bf3938a584c4896b1ec46e65e9a6e60.png

代码实现

// 客户端
public class ClientDemo {
  public static void main(String[] args) throws IOException {
    Socket socket = new Socket("127.0.0.1",10000);
    //是本地的流,用来读取本地文件的.
    BufferedInputStream bis = new BufferedInputStream(new
    FileInputStream("socketmodule\\ClientDir\\1.jpg"));
    //写到服务器 --- 网络中的流
    OutputStream os = socket.getOutputStream();
    BufferedOutputStream bos = new BufferedOutputStream(os);
    int b;
    while((b = bis.read())!=-1){
      bos.write(b);//通过网络写到服务器中
    }
    bos.flush();
    //给服务器一个结束标记,告诉服务器文件已经传输完毕
    socket.shutdownOutput();
    BufferedReader br = new BufferedReader(new
    InputStreamReader(socket.getInputStream()));
    String line;
    while((line = br.readLine()) !=null){
      System.out.println(line);
    }
    bis.close();
    socket.close();
  }
}
// 服务器
public class ServerDemo {
  public static void main(String[] args) throws IOException {
    ServerSocket ss = new ServerSocket(10000);
    Socket accept = ss.accept();
    //网络中的流,从客户端读取数据的
    BufferedInputStream bis = new
    BufferedInputStream(accept.getInputStream());
    //本地的IO流,把数据写到本地中,实现永久化存储
    BufferedOutputStream bos = new BufferedOutputStream(new
    FileOutputStream("socketmodule\\ServerDir\\copy.jpg"));
    int b;
    while((b = bis.read()) !=-1){
      bos.write(b);
    }
    BufferedWriter bw = new BufferedWriter(new
    OutputStreamWriter(accept.getOutputStream()));
    bw.write("上传成功");
    bw.newLine();
    bw.flush();
    bos.close();
    accept.close();
    ss.close();
  }
}

5. UDP发送数据

  • Java中的UDP通信
  • UDP协议是一种不可靠的网络协议,它在通信的两端各建立一个Socket对象,但是这两个
    Socket只是发送,接收数据的对象,因此对于基于UDP协议的通信双方而言,没有所谓的客
    户端和服务器的概念
  • Java提供了DatagramSocket类作为基于UDP协议的Socket
  • 构造方法

484e31de366743faa5a4459193d76356.png

相关方法

  • 发送数据的步骤
    - 创建发送端的Socket对象(DatagramSocket)
    - 创建数据,并把数据打包
    - 调用DatagramSocket对象的方法发送数据
    - 关闭发送端

代码演示

public class SendDemo {
  public static void main(String[] args) throws IOException {
    //创建发送端的Socket对象(DatagramSocket)
    // DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口
    DatagramSocket ds = new DatagramSocket();
    //创建数据,并把数据打包
    //DatagramPacket(byte[] buf, int length, InetAddress address, int port)
    //构造一个数据包,发送长度为 length的数据包到指定主机上的指定端口号。
    byte[] bys = "hello,udp,我来了".getBytes();
    DatagramPacket dp = new
    DatagramPacket(bys,bys.length,InetAddress.getByName("127.0.0.1"),10086);
    //调用DatagramSocket对象的方法发送数据
    //void send(DatagramPacket p) 从此套接字发送数据报包
    ds.send(dp);
    //关闭发送端
    //void close() 关闭此数据报套接字
    ds.close();
  }
}

6. UDP接收数据【应用】

  • 接收数据的步骤
  • 创建接收端的Socket对象(DatagramSocket)
  • 创建一个数据包,用于接收数据
  • 调用DatagramSocket对象的方法接收数据
  • 解析数据包,并把数据在控制台显示
  • 关闭接收端

构造方法

2a6d7ab624524099924d49fcb0c4cbcb.png

相关方法

f6bcd476025842ebba585381805a0c17.png示例代码

public class ReceiveDemo {
  public static void main(String[] args) throws IOException {
    //创建接收端的Socket对象(DatagramSocket)
    DatagramSocket ds = new DatagramSocket(12345);
    //创建一个数据包,用于接收数据
    byte[] bys = new byte[1024];
    DatagramPacket dp = new DatagramPacket(bys, bys.length);
    //调用DatagramSocket对象的方法接收数据
    ds.receive(dp);
    //解析数据包,并把数据在控制台显示
    System.out.println("数据是:" + new String(dp.getData(), 0,
    dp.getLength()));
    }
  }
}

7. UDP通信程序练习【应用】

  • 案例需求
  • UDP发送数据:数据来自于键盘录入,直到输入的数据是886,发送数据结束
  • UDP接收数据:因为接收端不知道发送端什么时候停止发送,故采用死循环接收

代码实现

/*
  UDP发送数据:
  数据来自于键盘录入,直到输入的数据是886,发送数据结束
*/
public class SendDemo {
  public static void main(String[] args) throws IOException {
    //创建发送端的Socket对象(DatagramSocket)
    DatagramSocket ds = new DatagramSocket();
    //键盘录入数据
    Scanner sc = new Scanner(System.in);
    while (true) {
      String s = sc.nextLine();
      //输入的数据是886,发送数据结束
      if ("886".equals(s)) {
        break;
      }
      //创建数据,并把数据打包
      byte[] bys = s.getBytes();
      DatagramPacket dp = new DatagramPacket(bys, bys.length,
      InetAddress.getByName("192.168.1.66"), 12345);
      //调用DatagramSocket对象的方法发送数据
      ds.send(dp);
    }
    //关闭发送端
    ds.close();
  }
}


/*
  UDP接收数据:
  因为接收端不知道发送端什么时候停止发送,故采用死循环接收
*/
public class ReceiveDemo {
  public static void main(String[] args) throws IOException {
    //创建接收端的Socket对象(DatagramSocket)
    DatagramSocket ds = new DatagramSocket(12345);
    while (true) {
      //创建一个数据包,用于接收数据
      byte[] bys = new byte[1024];
      DatagramPacket dp = new DatagramPacket(bys, bys.length);
      //调用DatagramSocket对象的方法接收数据
      ds.receive(dp);
      //解析数据包,并把数据在控制台显示
      System.out.println("数据是:" + new String(dp.getData(), 0,
      dp.getLength()));
    }
    //关闭接收端
    // ds.close();
  }
}

8. UDP三种通讯方式

  • 单播
    单播用于两个主机之间的端对端通信
  • 组播
    组播用于对一组特定的主机进行通信
  • 广播
    广播用于一个主机对整个局域网上所有主机上的数据通信

 

相关文章
|
1天前
|
网络协议 Unix 网络性能优化
|
1天前
|
网络协议 网络性能优化 网络架构
|
1天前
|
网络协议 网络性能优化
运输层中的UDP和TCP协议
总结来说,UDP适用于那些要求速度和实时性高于可靠性的应用,而TCP适用于要求数据可靠性和完整性的应用。选择使用哪种协议取决于您的应用需求。
10 1
|
3天前
|
网络协议 算法 网络性能优化
TCP 和 UDP哪个更好
TCP 和 UDP哪个更好
11 0
|
3天前
|
网络协议 程序员 API
LabVIEWCompactRIO 开发指南19 原始以太网(TCP/UDP)
LabVIEWCompactRIO 开发指南19 原始以太网(TCP/UDP)
|
2天前
|
安全 Java 调度
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第12天】 在现代软件开发中,多线程编程是提升应用程序性能和响应能力的关键手段之一。特别是在Java语言中,由于其内置的跨平台线程支持,开发者可以轻松地创建和管理线程。然而,随之而来的并发问题也不容小觑。本文将探讨Java并发编程的核心概念,包括线程安全策略、锁机制以及性能优化技巧。通过实例分析与性能比较,我们旨在为读者提供一套既确保线程安全又兼顾性能的编程指导。
|
1天前
|
Java
Java中的多线程编程:基础知识与实践
【5月更文挑战第13天】在计算机科学中,多线程是一种使得程序可以同时执行多个任务的技术。在Java语言中,多线程的实现主要依赖于java.lang.Thread类和java.lang.Runnable接口。本文将深入探讨Java中的多线程编程,包括其基本概念、实现方法以及一些常见的问题和解决方案。
|
1天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第13天】 在Java开发中,并发编程是一个复杂且重要的领域。它不仅关系到程序的线程安全性,也直接影响到系统的性能表现。本文将探讨Java并发编程的核心概念,包括线程同步机制、锁优化技术以及如何平衡线程安全和性能。通过分析具体案例,我们将提供实用的编程技巧和最佳实践,帮助开发者在确保线程安全的同时,提升应用性能。
10 1
|
2天前
|
Java 调度
Java一分钟之线程池:ExecutorService与Future
【5月更文挑战第12天】Java并发编程中,`ExecutorService`和`Future`是关键组件,简化多线程并提供异步执行能力。`ExecutorService`是线程池接口,用于提交任务到线程池,如`ThreadPoolExecutor`和`ScheduledThreadPoolExecutor`。通过`submit()`提交任务并返回`Future`对象,可检查任务状态、获取结果或取消任务。注意处理`ExecutionException`和避免无限等待。实战示例展示了如何异步执行任务并获取结果。理解这些概念对提升并发性能至关重要。
17 5
|
3天前
|
Java
Java一分钟:线程协作:wait(), notify(), notifyAll()
【5月更文挑战第11天】本文介绍了Java多线程编程中的`wait()`, `notify()`, `notifyAll()`方法,它们用于线程间通信和同步。这些方法在`synchronized`代码块中使用,控制线程执行和资源访问。文章讨论了常见问题,如死锁、未捕获异常、同步使用错误及通知错误,并提供了生产者-消费者模型的示例代码,强调理解并正确使用这些方法对实现线程协作的重要性。
14 3