【JavaSE】Java基础语法(四十一):TCP通信程序

简介: 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() 

注意事项

  1. accept方法是阻塞的,作用就是等待客户端连接
  2. 客户端创建对象并连接服务器,此时是通过三次握手协议,保证跟服务器之间的连接
  3. 针对客户端来讲,是往外写的,所以是输出流
    针对服务器来讲,是往里读的,所以是输入流
  1. read方法也是阻塞的
  2. 客户端在关流的时候,还多了一个往服务器写结束标记的动作
  3. 最后一步断开连接,通过四次挥手协议保证连接终止

  • 三次握手
  • 四次挥手

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();
  }
}

相关文章
|
25天前
|
Java Maven 数据安全/隐私保护
如何实现Java打包程序的加密代码混淆,避免被反编译?
【10月更文挑战第15天】如何实现Java打包程序的加密代码混淆,避免被反编译?
40 2
|
28天前
|
安全 Java Linux
java程序设置开机自启
java程序设置开机自启
|
1月前
|
运维 Java Linux
【运维基础知识】Linux服务器下手写启停Java程序脚本start.sh stop.sh及详细说明
### 启动Java程序脚本 `start.sh` 此脚本用于启动一个Java程序,设置JVM字符集为GBK,最大堆内存为3000M,并将程序的日志输出到`output.log`文件中,同时在后台运行。 ### 停止Java程序脚本 `stop.sh` 此脚本用于停止指定名称的服务(如`QuoteServer`),通过查找并终止该服务的Java进程,输出操作结果以确认是否成功。
34 1
|
1月前
|
Java Python
如何通过Java程序调用python脚本
如何通过Java程序调用python脚本
25 0
|
6天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
15天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
2天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
15 9
|
5天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
2天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
5天前
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
15 3