当前位置: 首页 > news >正文

JAVAEE值网络编程(2)_TCP流套接字及通信模型、TCP网络编程及代码实例

前言

 在上一节内容中,我们介绍了什么是套接字,以及使用UDP数据报套接字网络编程, 最后我们还介绍了Java数据报套接字通信模型以及相关代码实例。在这一节我们将会介绍TCP流套接字编程。


一、流套接字及通信模型

1.1 TCP套接字

TCP,即Transmission Control Protocol(传输控制协议),是传输层协议。

TCP主要特点:(会在后续单独章节中详细介绍)

  1. 有连接
  2. 可靠传输
  3. 面向字节流
  4. 有接收、发送缓冲区
  5. 大小不限

对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。

1.2 原始套接字

 原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

1.3 Java流套接字通信模型

在这里插入图片描述
注意事项:

  1. 客户端和服务端:开发时,经常是基于一个主机开启两个进程作为客户端和服务端,但真实的场景,一般都是不同主机。
  2. 注意目的IP和目的端口号,标识了一次数据传输时要发送数据的终点主机和进程
  3. Socket编程我们是使用流套接字和数据报套接字,基于传输层的TCP或UDP协议,但应用层协议也需要考虑。
  4. 端口占用问题:如果一个进程A已经绑定了一个端口,再启动一个进程B绑定该端口,就会报错,这种情况也叫端口被占用
  5. 解决端口被占用的问题:
    如果占用端口的进程A不需要运行,就可以关闭A后,再启动需要绑定该端口的进程B;
    如果需要运行A进程,则可以修改进程B的绑定端口,换为其他没有使用的端口。

二、TCP流套接字编程

2.1 ServerSocket API

ServerSocket 是创建TCP服务端Socket的API,ServerSocket构造方法如下:
在这里插入图片描述
 另外,ServerSocket 相关方法如下:
在这里插入图片描述

2.2 Socket API

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。
 Socket的构造方法如下:
在这里插入图片描述
 Socket相关方法:
在这里插入图片描述

2.3 TCP中的长短连接

TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:

短连接:每次接收到数据并返回响应后,都关闭连接,短连接只能一次收发数据。
长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,长连接可以多次收发数据。

TCP长短连接对比:

  1. 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。
  2. 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
  3. 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。

三、代码实例

3.1 TCP 客户端

package network;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.ref.SoftReference;
import java.net.Socket;
import java.util.Scanner;/*** @author Zhang* @date 2024/5/2115:13* @Description:*/
public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serverIP,int serverPort) throws IOException {// 此时,需要在创建 Socket 的同时,和服务器”建立连接“,此时就得告诉 Socket 服务器在哪里socket = new Socket(serverIP,serverPort);}public void start(){Scanner scanner = new Scanner(System.in);try(InputStream  inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()){PrintWriter writer = new PrintWriter(outputStream);Scanner scannerNetwork = new Scanner(inputStream);while (true){// 1. 从控制台读取用户输入的内容System.out.print("-->");String request = scanner.next();// 2. 把字符串作为请求,发给服务器//    这里用println,是为了让后后面请求带上换行,也就是和服务器读取请求,scanner.next 呼应writer.println(request);writer.flush();// 3. 读取服务器返回的响应String response = scannerNetwork.next();// 4. 在界面上显示内容System.out.println(response);}} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);client.start();}
}

3.2 TCP 服务端

package network;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;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @author Zhang* @date 2024/5/2115:13* @Description:*/
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("服务器启动!");ExecutorService service = Executors.newCachedThreadPool();  //创建线程池while (true){//通过 accept 方法,把内核中已经建立好的连接那回到应用程序中Socket clientSocket = serverSocket.accept();/***  此处不能直接调用processConnection,这会导致服务器不能处理多个客户端,通过创建新的线程来调用是更合理的方法*             Thread t = new Thread(()->{*                 try {*                     processConnection(clientSocket);*                 } catch (IOException e) {*                     throw new RuntimeException(e);*                 }*             });*            t.start();*///使用创建线程的方式开销会比较大,此处我们使用线程池的方式service.submit(new Runnable() {@Overridepublic void run() {try {processConnection(clientSocket);} catch (IOException e) {throw new RuntimeException(e);}}});}}// 通过这个方法,来处理当前的连接private void processConnection(Socket clientSocket) throws IOException {//进入方法,先打印一个日志System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress(),clientSocket.getPort());//InputStream 和OutputStream就是在字节流,可以借助这两个对象,完成数据的“发送”和“接收”//通过InputStream 进行read 操作,就是“接收”操作(站在CPU角度)//通过OutputStream 进行 writ额操作,就是“发送”操作。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);printWriter.println(response);  //此处的打印是写入到outputStream 对应的流对象中,也就是写入到 clientSocketprintWriter.flush();  //刷新缓冲区,如果没有此操作,数据仍然可能在内存中,没有被写入网卡// 4.打印一下这次请求交互的内容System.out.printf("[%s:%d] req=%s resp=%s\n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);}}catch (IOException e){e.printStackTrace();}finally {//在这个地方进行clientSocket的关闭,processConnection就是处理一个连接,如果这个方法执行完毕,这个连接也就处理完了clientSocket.close();}}public String process(String request){// 此处也是写的服务器,响应和请求一样return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(9090);server.start();}
}

启动客户端和服务器

运行结果:

//客户端发送请求
TcpEchoClient:-->张三
张三
-->
----------------------------------
//服务器响应
TcpEchoServer:服务器启动!
[/127.0.0.1:60107] 客户端上线
[/127.0.0.1:60107] req=张三 resp=张三

相关文章:

JAVAEE值网络编程(2)_TCP流套接字及通信模型、TCP网络编程及代码实例

前言 在上一节内容中,我们介绍了什么是套接字,以及使用UDP数据报套接字网络编程, 最后我们还介绍了Java数据报套接字通信模型以及相关代码实例。在这一节我们将会介绍TCP流套接字编程。 一、流套接字及通信模型 1.1 TCP套接字 TCP&#xff0…...

【MMU】——MMU 页命中/缺页

文章目录 MMU 页命中/缺页MMU 命中MMU 缺页 MMU 页命中/缺页 MMU 命中 处理器产生一个虚拟地址。MMU生成 PTE 地址,并从高速缓存/主存请求得到它。高速缓存/主存向 MMU 返回 PTE。MMU 构造物理地址,并把它传送给高速缓存/主存。高速缓存/主存返回所请求…...

Win32和c++11多线程

Win32和c11多线程 一、概念1.线程的特点线程内核对象线程控制块线程是独立调度和分派的基本单位共享进程的资源 2.线程的上下文切换引起上下文切换的原因 3.线程的状态 二、Windows多线程API1.CreateThread创建线程2.获取线程ID3.关闭线程句柄4.挂起线程5.恢复线程6.休眠线程的…...

关于python包导入问题的重思考

将顶层目录直接设置为一个包 像这样,每一个文件从顶层包开始导入 这样可以解决我的问题,但是要注意的时,要避免使用出现上下级出现同名包的情况,比如: AutoServer--AutoServer--__init__.py--__init__.py这种情况下…...

攻防世界---misc---津门杯2021-m1

1、题目描述,下载附件是一张bmp格式的图片 2、直觉告诉我这和图片的颜色通道有关 3、于是我就尝试用stegslove打开图片 4、将颜色通道都改为0,点击preview 5、然后发现一串base64编码 6、解码得flag flag{l5DGqF1pPzOb2LU919LMaBYS5B1G01FD}...

【计算机视觉(8)】

基于Python的OpenCV基础入门——图像直方图 直方图图像直方图 图像直方图代码以及实现效果 直方图 直方图是一种用于描述图像亮度分布的统计工具。它将图像的像素亮度值按照不同的亮度等级进行计数,并以直方图的形式呈现出来。图像直方图可以显示图像中每个亮度级别…...

Linux操作系统:Redis在虚拟环境下的安装与部署

Redis下载方法 最近部署项目的时候用到了Redis,自己在安装的时候也碰到了一些列问题最终安装成功,记录一下自己的安装历程。前期准备: 服务器Linux版本:Centos8.4 64位(http://isoredirect.centos.org/centos/8/isos/…...

哈希表和二维矩阵的结合-2352. 相等行列对(新思路、新解法)

题目链接及描述 . - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/equal-row-and-column-pairs/description/?envTypest…...

深度学习中无监督学习

深度学习中的无监督学习 无监督学习(Unsupervised Learning)是一种机器学习方法,在没有标签数据的情况下,从数据中提取有意义的模式和特征。无监督学习广泛应用于深度学习中,以解决数据标注困难和大量无标签数据存在的…...

JVM基础知识

一、JVM的内存区域划分 一个进程在运行的时候,会向操作系统申请到内存资源,从来存放程序运行的相关数据。 JVM本质上就是一个java进程,在运行的时候也会从操作系统那搞一块内存,供Java代码执行使用。 JVM又把申请的一块内存根据不同的用途划分出了不同区域。 每一…...

618网购节,电商能挡住恶意网络爬虫的攻击吗?

目录 爬虫盗取电商数据的步骤 电商平台如何发现网络爬虫? 如何拦截违法网络爬虫 2023年,杭州中院审结了两起涉及“搬店软件”的不正当竞争案件。本案的原告是国内某大型知名电子商务平台的运营主体,而被告则是开发了一款名为“某搬家快速商品…...

Codeforces Round 951 (Div. 2) C、D(构造、线段树)

1979C - Earning on Bets 构造题:观察到k范围很小,首先考虑最终硬币总数可以是多少,我们可以先假设最终的硬币总数为所有k取值的最小公倍数,这样只需要满足每个结果添加1枚硬币即可赚到硬币。 // Problem: C. Earning on Bets //…...

elmentUI el-table 总结行

背景 原因:表格展示的都是明细数据,需要对当前的明细数据的部分字段进行汇总难点:汇总的条件不一定,有时候客户查的是1天,有时候是10天 官方写法 只开启开关 开启汇总开关如果没有汇总方法, 会自动汇总所有…...

【大数据】计算引擎:Spark核心概念

目录 前言 1.什么是Spark 2.核心概念 2.1.Spark如何拉高计算性能 2.2.RDD 2.3.Stage 3.运行流程 前言 本文是作者大数据系列中的一文,专栏地址: https://blog.csdn.net/joker_zjn/category_12631789.html?spm1001.2014.3001.5482 该系列会成体…...

Python | C# | MATLAB 库卡机器人微分运动学 | 欧拉-拉格朗日动力学 | 混合动力控制

🎯要点 🎯正向运动学几何矩阵,Python虚拟机器人模拟动画二连杆平面机械臂 | 🎯 逆向运动学几何矩阵,Python虚拟机器人模拟动画三连杆平面机械臂 | 🎯微分运动学数学形态,Python模拟近似结果 | …...

Signac|成年小鼠大脑 单细胞ATAC分析(1)

引言 在本教程中,我们将探讨由10x Genomics公司提供的成年小鼠大脑细胞的单细胞ATAC-seq数据集。本教程中使用的所有相关文件均可在10x Genomics官方网站上获取。 本教程复现了之前在人类外周血单核细胞(PBMC)的Signac入门教程中执行的命令。…...

【POSIX】运行时so库动态加载

运行时可以自己自定义so库的动态加载框架&#xff0c;主动去加载某些库&#xff0c;并调用其中的某些方法 首先写一些方法&#xff0c;并生成so库 // hello.cpp#include <iostream>/*使用 nm 命令查看 so 库的内容 */// 1. 使用extern // dlsym(handle, "hello&qu…...

爱普生SG2520CAA汽车电子中控专用晶振

随着汽车电子技术的飞速发展&#xff0c;汽车中控系统变得越来越智能化和复杂化。为了确保这些系统的高性能和高可靠性&#xff0c;选择符合AEC-Q200标准的高品质晶振至关重要。爱普生SG2520CAA晶振凭借其优异的特性&#xff0c;成为汽车电子中控系统的理想选择。 爱普生晶振SG…...

Vue——监听器简单使用与注意事项

文章目录 前言编写简单demo注意事项 前言 监听器&#xff0c;在官网中称为侦听器&#xff0c;个人还是喜欢称之为监听器。官方文档如下&#xff1a; vue 官网 侦听器 编写简单demo 侦听器在项目中通常用于监听某个属性变量值的变化&#xff0c;并根据该变化做出一些处理操作。…...

OpenCV的“画笔”功能

类似于画图软件的自由笔刷功能&#xff0c;当按住鼠标左键&#xff0c;在屏幕上画出连续的线条。 定义函数&#xff1a; import cv2 import numpy as np# 初始化参数 drawing False # 鼠标左键按下时为True ix, iy -1, -1 # 鼠标初始位置# 鼠标回调函数 def mouse_paint(…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术&#xff0c;说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号&#xff08;调制&#xff09; 把信息从信号中抽取出来&am…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1&#xff1a;HTML/CSS 前端高频面试题2&#xff1a;浏览器/计算机网络 前端高频面试题3&#xff1a;JavaScript 1.什么是强缓存、协商缓存&#xff1f; 强缓存&#xff1a; 当浏览器请求资源时&#xff0c;首先检查本地缓存是否命中。如果命…...