【JavaEE初阶系列】——网络编程 TCP客户端/服务器 程序实现

目录

🚩TCP流套接字编程

🍭ServerSocket API

🍭Socket API

🍭TCP服务器

🍭TCP客户端


🚩TCP流套接字编程

俩个关键的类 

  • ServerSocket (给服务器使用的类,使用这个类来绑定端口号)
  • Socket(既会给服务器用,又会给客户端用)

这俩个类都是用来表示socket文件的。(抽象了网卡这样的硬件设备)


🍭ServerSocket API

ServerSocket 是创建 TCP 服务端 Socket API
ServerSocket 构造方法:
方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口
ServerSocket 方法:
方法签名方法说明
Socket accept()开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待
void close()关闭此套接字

🍭Socket API

Socket 是客户端 Socket ,或服务端中接收到客户端建立连接( accept 方法)的请求后,返回的服务端Socket。
不管是客户端还是服务端 Socket ,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
Socket 构造方法:
方法签名方法说明
Socket(String host,int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程连接。

Socket方法:

方法签名方法说明
InetAddress.getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

TCP是有连接的,连接就意味着通信双方会记录保存对端的信息,UDP来说,每次发送数据都得手动send方法中指定目标地址(UDP自身没有存储这个消息)TCP来说,则不需要,前提是需要先把连接给建立上。那么,如果建立连接呢?不需要代码干预,是系统内核自动负责完成的,对应app来说,客户端这边,主要是要发起”建立连接"动作,服务器这边,主要要把建立好的连接从内核中拿到app里。

我们看到大型商场里,都有很有海底捞,每天海底捞的人是非常多的,你要想去吃海底捞,就要排号。我们给海底捞店当作应用程序。而内核就是一个队列等待着去吃海底捞,每当有客人吃完,走了,空出了一桌,服务员就会叫号。

如果有客户端和服务器建立连接,这个时候服务器的应用程序是不需要任何操作(也没有任何感知的),内核直接完成了连接建立的流程(三次握手),完成流程之后,就会在内核的队列中(这个队列是每个serverSocket都有一个这样的队列)排队。

应用程序要想和客户端进行通信,就需要通过一个accept方法把内核队列里已经建立好的连接对象,拿到app中。


TCP中用ServerSocket (给服务器使用的类,使用这个类来绑定端口号),服务器启动之后用到accept方法,把内核中建立好的连接到应用程序中去(建立连接的过程是内核自动完成的,应用程序是捡漏的),如果没有与客户端连接,那么就阻塞等待。

  private ServerSocket serverSocket=null;public TCPEchoServer(int port) throws IOException {serverSocket =new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器正式启动");while (true){//通过accpet方法,把内核中已经建立好的连接拿到app中//建立连接的细节流程都是内核自动完成的,app只需要“捡现成”的Socket clientSocket=serverSocket.accept();}}

在销售A卖楼盘的时候,销售在路上看到一个人想找一个人问问需不需要买房,然后那个男生就带去楼盘区,然后销售找了一个专业的置业顾问B,来介绍楼盘。而这个销售就去路上继续找人。

A:在外面招揽客人

B:给客人提供详细的服务

然后我们调用方法来处理当前的连接。首先我们先打印一个日志,表示已经与客户端建立连接了。

  • getPort() 和 getInetAddress() 得到对端的IP和端口 (客户端)
  • getLocalAddress() 和getLocalPort() 得到本地的IP和端口(服务器)
 //打印这个日志,来表示客户端连上了System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());

  • 首先我们接收请求,用Scanner包装输入流,并读取请求。
  • 然后我们根据请求,计算响应
  • 最后把响应写回客户端 ,用PrintWriter类进行包装输出流,并flush().
 Scanner scanner=new Scanner(inputStream);//1.读取请求并解析,此处就以next来作为读取请求的方式,.next的规则是,读到“空白符”就返回String request=scanner.next();//2.根据请求,计算响应String response=process(request);
//3.把响应写回客户端//可以把String转成字节数组,写入到OutputStream,
//也可以使用PrintWriter把OutputStream包裹一下,来写入字符串PrintWriter printWriter=new PrintWriter(outputStream);
//此处的println不是打印到控制台了,而是写入到outputStream对应的流对象,也就是写入到clientSocket
//自然这个数据也就通过网络发送出去了,//此处使用println带有\n 也是为了后续 客户端这边 可以使用 scanner.next来读取数据printWriter.write(response);

空白符 是一类特殊的字符,换行,回车符,空格,制表符,翻页符,垂直制表符

后续客户端发起的请求,会以空白符作为结束标记(此处就约定使用\n)


🍭TCP服务器

package TCP;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;public class TCPEchoServer {private ServerSocket serverSocket=null;public TCPEchoServer(int port) throws IOException {serverSocket =new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器正式启动");while (true){//通过accpet方法,把内核中已经建立好的连接拿到app中//建立连接的细节流程都是内核自动完成的,app只需要“捡现成”的Socket clientSocket=serverSocket.accept();Thread t=new Thread(()->{processConnection(clientSocket);});t.start();}}//通过这个方法,来处理当前的连接public void processConnection(Socket clientSocket) {//打印这个日志,来表示客户端连上了System.out.printf("[%s:%d] 客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());try(InputStream inputStream=clientSocket.getInputStream();OutputStream outputStream=clientSocket.getOutputStream()) {//使用try()方式,避免后续用完了流对象,忘记关闭//由于客户端发来的数据,可能是"多条数据“,针对多条数据,就循环处理while (true){Scanner scanner=new Scanner(inputStream);if(!scanner.hasNext()){//连接断开了,此时循环就应该结束System.out.printf("[%s:%d] 客户端下线!\n",clientSocket.getInetAddress(),clientSocket.getPort());break;}//1.读取请求并解析,此处就以next来作为读取请求的方式,.next的规则是,读到“空白符”就返回String request=scanner.next();//2.根据请求,计算响应String response=process(request);//3.把响应写回客户端//可以把String转成字节数组,写入到OutputStream,//也可以使用PrintWriter把OutputStream包裹一下,来写入字符串PrintWriter printWriter=new PrintWriter(outputStream);//此处的println不是打印到控制台了,而是写入到outputStream对应的流对象,也就是写入到clientSocket//自然这个数据也就通过网络发送出去了,//此处使用println带有\n 也是为了后续 客户端这边 可以使用 scanner.next来读取数据printWriter.println(response);//此处还要记得有个操作,刷新缓冲区,如果没有刷新操作,可能数据仍然是在内存中,没有被写入网卡printWriter.flush();//打印了这次请求交互过程的内容System.out.printf("[%s:%d] req=%s resp=%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}finally {//进行clientSocket的关闭try {clientSocket.close();} catch (IOException e) {throw new RuntimeException(e);}}}public String process(String request){return request;}public static void main(String[] args) throws IOException {TCPEchoServer tcpEchoServer=new TCPEchoServer(9090);tcpEchoServer.start();}
}

如果我们出现了多个客户端连接同一个服务器该怎么办呢?这就考虑到多线程的知识了,如果有客户端就开启线程。


🍭TCP客户端

  private Socket socket=null;public TCPClient(String serverIP, int serverPort) throws IOException {//需要在创建Socket的同时,和服务器”建立连接“ 此时就得告诉Socket服务器在哪里//具体建立连接的细节,不需要咱们代码手动干预,是内核自动负责的//当我们new这个对象的时候,操作系统内核,就开始使用 三次握手 具体细节 完成建立连接的过程socket =new Socket(serverIP,serverPort);}

TCP是连接的,我们需要对端的IP和端口号。所以我们要构造服务器的IP和端口号。

客户端是发出请求,并接收服务器返回的响应。

  • 我们先输入,并判断是否有输入,如果有输入就返回字符串。
  • 发出请求,就是用PrintWriter类来封装输出流,并flush()。
  • 然后接收服务器返回的响应,用Scanner来封装输入流。然后调用next()方法返回String字符串
  • 然后打印处理。
package TCP;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TCPClient {private Socket socket=null;public TCPClient(String serverIP, int serverPort) throws IOException {//需要在创建Socket的同时,和服务器”建立连接“ 此时就得告诉Socket服务器在哪里//具体建立连接的细节,不需要咱们代码手动干预,是内核自动负责的//当我们new这个对象的时候,操作系统内核,就开始使用 三次握手 具体细节 完成建立连接的过程socket =new Socket(serverIP,serverPort);}public void start(){System.out.println("客户端启动");//tcp客户端行为和udp客户端差不多//从服务器读取响应//把响应显示到界面上Scanner scanner=new Scanner(System.in);try(InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()) {Scanner scanner1=new Scanner(inputStream);while (true){//1.从控制台输入内容System.out.println("->");String request=scanner.next();//2.把字符串作为请求,发送给服务器PrintWriter printWriter=new PrintWriter(outputStream);printWriter.println(request);printWriter.flush();//3.读取服务器返回的响应String response=scanner1.next();//4.界面显式内容System.out.println(response);}} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException {TCPClient tcpClient=new TCPClient("172.20.10.2",9090);tcpClient.start();}
}

你跑的快,耳边全是风声。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/811189.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言程序与设计——工程项目开发

之前我们已经了解了C语言的基础知识部分,掌握这些之后,基本就可以开发一些小程序了。在开发时,就会出现合作的情况,C语言是如何协作开发的呢,将在这一篇文章进行演示。 工程项目开发 在开发过程中,你接到…

【算法每日一练]-图论(lca) 最近公共祖先LCA,货车运输

目录 P3379:最近公共祖先LCA 思路: 货车运输 P3379:最近公共祖先LCA 思路: 首先进行的预处理,将所有点的深度和p数组求出来 设置:p[i][j]存的从i向上走2的j次方那么长的路径到的父节点 更深的点走到和…

PostgreSQL入门到实战-第二十二弹

PostgreSQL入门到实战 PostgreSQL中表连接操作(六)官网地址PostgreSQL概述PostgreSQL中self-join命令理论PostgreSQL中self-join命令实战更新计划 PostgreSQL中表连接操作(六) 使用PostgreSQL自联接技术来比较同一表中的行 官网地址 声明: 由于操作系统, 版本更新等原因, 文…

内存函数memcpy、mommove、memset、memcmp

1、memcpy函数 描述: C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1。 声明: void *memcpy(void *str1, const void *str2, size_t n)参数: str1 -- 指向用于存储复制内容的目标…

【电控笔记0】稳定度判断

简要概括 现控:原理虚轴,稳定度越高 自控:相位裕度PM 增益裕度GM 开环传函 不稳定条件判断

期望阻抗(Zd/s或Yd*s)的nyquist、bode与rlocus

在机器人控制领域中,针对具体的阻抗参数特性(如质量、阻尼和刚度),Nyquist图、Bode图和根轨迹(rlocus)可以提供深入的分析和设计工具。 Nyquist图: 应用于阻抗参数:在机器人控制中&…

docker pull镜像的时候指定arm平台

指定arm平台 x86平台下载arm平台的镜像包 以mysql镜像为例 docker pull --platform linux/arm64 mysqldocker images查看镜像信息 要查看Docker镜像的信息,可以使用docker inspect命令。这个命令会返回镜像的详细信息,包括其元数据和配置。 docker i…

Fast-lio2运行时如何显示轨迹线

修改对应设备的.yaml文件,以velodyne为例: 将 path_en参数改为true即可,运行其他设备,修改对应的参数

四、SpringBoot3 整合 Druid 数据源

本章概要 创建程序引入依赖启动类配置文件编写编写 Controller启动测试问题解决 4.1 创建程序 4.2 引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://ww…

【C++ STL序列容器】deque 双端队列

文章目录 【 1. 基本原理 】【 1. deque 的创建 】1.1 创建一个空的 deque1.2 创建一个 n 个默认值的 deque1.3 创建一个 n 个指定值的 deque1.4 通过一个 deque 初始化另一个 deque1.5 通过基础容器来初始化 queue 容器适配器 【 3. deque 支持的成员函数 】 【 1. 基本原理 】…

不惑之年,反思我如何成为一个程序员

不惑之年&#xff0c;反思我如何成为一个程序员 文章目录 不惑之年&#xff0c;反思我如何成为一个程序员01/偶然掉入码河02/现实撕碎理想03/发展选择方向04/时代成就向往05/幸运装饰未来 在这个充满生机与希望的季节&#xff0c;博主有幸收到一家国企邀约面试&#xff0c;并顺…

通俗易懂HTTP和HTTPS区别

HTTP&#xff1a;超文本传输协议&#xff0c;它是使用一种明文的方式发送我们的内容&#xff0c;没有任何的加密&#xff0c;例如我们要在网页上输入账号密码&#xff0c;如果使用HTTP协议&#xff0c;账号密码就可能会被暴露&#xff0c;默认端口是80. HTTPS&#xff1a;是HT…

护眼台灯品牌哪个好?2024五大护眼台灯排行榜分享

​护眼台灯作为家庭中常见的照明工具&#xff0c;其存在几乎成为了现代生活的标配。家长们往往会为孩子购置一台&#xff0c;供学习和阅读使用&#xff1b;同时&#xff0c;它也是学生和办公人员在夜晚工作学习的必备之物。然而&#xff0c;市面上的一些普通台灯可能存在着种种…

Springboot使用教程

二、配置文件 SpringBoot使用一个全局的配置文件&#xff0c;配置文件名是固定的&#xff1b; •application.properties •application.yml 1.配置文件的作用&#xff1a; 修改SpringBoot自动配置的默认值&#xff1b;SpringBoot在底层都给我们自动配置好&#xff1b; Y…

OpenHarmony的C/C++三方库的适配

简介 本仓库主要用于存放已经适配OpenHarmony的C/C三方库的适配脚本和OpenHarmony三方库适配指导文档、三方库适配相关的工具。 三方库适配 本仓库的三方库主要是通过OpenHarmony SDK进行交叉编译适配的&#xff0c;并集成到应用端进行使用。 在使用OpenHarmony的SDK进行交…

智能合约:未来数字经济的基石

智能合约是一种自动执行交易的计算机协议&#xff0c;它以代码形式规定了交易双方的权利和义务&#xff0c;具有高度的可靠性和安全性。随着数字经济的发展&#xff0c;智能合约的重要性日益凸显&#xff0c;将成为未来数字经济的基石。 首先&#xff0c;智能合约在金融领域的应…

【目标检测数据集】城市街道垃圾堆相关数据集

一、GarbageOverflow&#xff1a;城市街道垃圾堆数据集 该垃圾堆数据集是通过爬虫从网上进行爬取得到的&#xff0c;一共包含1188张图片&#xff0c;有2个类别&#xff0c;分别为[overflow, No Overflow]&#xff0c;两个标签的数量分别为1734个标签和414个标签。部分数据集及…

23年坚守,只为打造高品质立秀膨体,索康让品质为中国说话

2024年3月23日&#xff0c;第二十三届上海国际整形美容外科大会&#xff08;以下简称“大会”&#xff09;在上海召开&#xff0c;本次大会由张涤生整形外科发展基金会主办&#xff0c;上海交通大学附属第九人民医院整复外科、Chinese Journal of Plastic and Reconstructive S…

阿里云2核2G服务器这么便宜,能用来做什么?

阿里云2核2G服务器这么便宜&#xff0c;能用来做什么&#xff1f;阿里云2核2G云服务器可以用来搭建网站、爬虫、邮件服务器、接口服务器、个人博客、企业官网、数据库应用、大数据计算、AI人工智能、论坛、电子商务、AI、LLM大语言模型、测试环境等&#xff0c;阿里云2核2G服务…

Uniapp+基于百度智能云完成AI视觉功能(附前端思路)

本博客使用uniapp百度智能云图像大模型中的AI视觉API&#xff08;本文以物体检测为例&#xff09;完成了一个简单的图像识别页面&#xff0c;调用百度智能云API可以实现快速训练模型并且部署的效果。 uniapp百度智能云AI视觉页面实现 先上效果图实现过程百度智能云Easy DL训练图…