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

Java网络通信TCP

目录

TCP两个核心类

服务端

1.用ServerSocker类创建对象并且手动指定端口号

2.accept阻塞连接服务端与客户端

3.给客户端提供处理业务方法

4.处理业务

整体代码

客户端

1.创建Socket对象,并连接服务端的ip与端口号

2.获取Socket流对象,写入数据,阻塞等待服务端响应

整体代码

jconsole用来监控java线程


TCP两个核心类

ServerSocket 服务器使用socket

accept没有参数 返回值是一个Socket对象

功能是等待服务器和客户端建立连接,建立成功后则会把这个连接获取到进程中。接下来就通过Scoket返回的对象来进行交互

Scoket服务器和客户端都使用socket

通过socket对象就可以进行发送接收数据

socket内部包含了输入流对象(接收) 输出流对象 (发送)

服务端

1.用ServerSocker类创建对象并且手动指定端口号

    private ServerSocket serverSocket=null;public Test1(int port) throws IOException {serverSocket=new ServerSocket(port);

2.accept阻塞连接服务端与客户端

当我们用UDP那样连接客户端会出现一个问题

UDP是无连接的,他发送数据时直接用地址端口号发送

而TCP是有连接的,当我们用accept连接时,ProcessConnect方法会一直被循环执行单个客户端,而其他客户端要连接时,无法执行到accept,必须等待ProcessConnect方法执行结束,所以会被阻塞。简单来说就是当有一个客户端连接时,其他客户端必须等待连接的客户端断开连接才能连接,还是一个个来连接。

所以ProcessConnect方法我们直接交给线程去执行,这样其他客户端来连接时,直接让线程去执行处理客户端业务。

所以我们可以用到多线程

既然用到了多线程,就可以用出线程池,效率会更高。

public void start() throws IOException {System.out.println("服务器启动");while (true){//阻塞等待服务器与客户端建立连接Socket socket=serverSocket.accept();//若没线程 当一个客户端连接后 会一直在ProcessConnect内//其他客户端连接时 必须要等待ProcessConnect结束,进入下一次循环,才能执行到Socketsocket=serverSocket.accept(); 才能连接下一个客户端
//           // ProcessConnect(socket);//所以执行处理客户端请求,我们让线程去干,这样就不会在一个线程内阻塞
//            Thread thread=new Thread(()->{
//                try {
//                    ProcessConnect(socket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            thread.start();//线程池ExecutorService executorService= Executors.newCachedThreadPool();executorService.submit(new Runnable() {@Overridepublic void run() {try {ProcessConnect(socket);} catch (IOException e) {throw new RuntimeException(e);}}});}}

3.给客户端提供处理业务方法

我们可以直接获取Socket内的流对象,直接写入读出即可

需要注意,写入数据时,因为时流对象接收,要\n等待其他结束,而我们输入数据时,流对象是不会写入\n的,所以我们可以在数据后自动添加\n 或者用println默认有个\n

public void ProcessConnect(Socket socket) throws IOException {//实际他们交流数据是一个为socket类型的文件System.out.printf("[地址:%s:端口号%d]建立连接成功\n",socket.getInetAddress().toString(),socket.getPort());try (InputStream inputStream = socket.getInputStream();//获取socket内部的input流OutputStream outputStream = socket.getOutputStream())//获取socket内部的output流{Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);//长连接写法while (true) {if(!scanner.hasNext()){System.out.printf("[地址:%s:端口号%d]断开连接",socket.getInetAddress().toString(),socket.getPort());}//从客户端接收数据String resqust = scanner.next();System.out.println("服务器接收数据");//处理数据String response = process(resqust);System.out.println("服务器处理数据");//因为这用流接收 我们按下换行是被scanner接收但并未添加到数据内 而服务器接收流收到的数据内//是没有换行符的 就会一直阻塞 所以我们要在数据后再加个\n//服务器发送数据//printWriter.write(response+'\n');//或者直接使用println自带\nprintWriter.println(response);System.out.println("服务器发送数据");//刷新缓冲区printWriter.flush();System.out.printf("[地址:%s:端口号:%d]接收数据:%s 响应数据:%s",socket.getInetAddress().toString(),socket.getPort(),resqust,response);}}}

4.处理业务

这里是为了演示TCP连接,所以只写个简单回传

public String process(String s){return s;}

整体代码

package TestTCP;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.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;//服务器
public class Test1 {private ServerSocket serverSocket=null;public Test1(int port) throws IOException {serverSocket=new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动");while (true){//阻塞等待服务器与客户端建立连接Socket socket=serverSocket.accept();//若没线程 当一个客户端连接后 会一直在ProcessConnect内//其他客户端连接时 必须要等待ProcessConnect结束,进入下一次循环,// 才能执行到Socketsocket=serverSocket.accept(); 才能连接下一个客户端
//            ProcessConnect(socket);//所以执行处理客户端请求,我们让线程去干,这样就不会在一个线程内阻塞
//            Thread thread=new Thread(()->{
//                try {
//                    ProcessConnect(socket);
//                } catch (IOException e) {
//                    throw new RuntimeException(e);
//                }
//            });
//            thread.start();//线程池ExecutorService executorService= Executors.newCachedThreadPool();executorService.submit(new Runnable() {@Overridepublic void run() {try {ProcessConnect(socket);} catch (IOException e) {throw new RuntimeException(e);}}});}}//给当前客户端提供服务方法public void ProcessConnect(Socket socket) throws IOException {//实际他们交流数据是一个为socket类型的文件System.out.printf("[地址:%s:端口号%d]建立连接成功\n",socket.getInetAddress().toString(),socket.getPort());try (InputStream inputStream = socket.getInputStream();//获取socket内部的input流OutputStream outputStream = socket.getOutputStream())//获取socket内部的output流{Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);//长连接写法while (true) {if(!scanner.hasNext()){System.out.printf("[地址:%s:端口号%d]断开连接",socket.getInetAddress().toString(),socket.getPort());}//从客户端接收数据String resqust = scanner.next();System.out.println("服务器接收数据");//处理数据String response = process(resqust);System.out.println("服务器处理数据");//因为这用流接收 我们按下换行是被scanner接收但并未添加到数据内 而服务器接收流收到的数据内//是没有换行符的 就会一直阻塞 所以我们要在数据后再加个\n//服务器发送数据//printWriter.write(response+'\n');//或者直接使用println自带\nprintWriter.println(response);System.out.println("服务器发送数据");//刷新缓冲区printWriter.flush();System.out.printf("[地址:%s:端口号:%d]接收数据:%s 响应数据:%s",socket.getInetAddress().toString(),socket.getPort(),resqust,response);}}}public String process(String s){return s;}public static void main(String[] args) throws IOException {Test1 t1=new Test1(8080);t1.start();}
}

客户端

1.创建Socket对象,并连接服务端的ip与端口号

    private Socket socket=null;public Test2() throws IOException {socket=new Socket("127.0.0.1",8080);

2.获取Socket流对象,写入数据,阻塞等待服务端响应

    public void start() throws IOException {try(InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()){while (true){Scanner scanner=new Scanner(inputStream);PrintWriter printWriter=new PrintWriter(outputStream);Scanner scanner1=new Scanner(System.in);System.out.println("输入数据>");String requst=scanner1.next();//因为这用流接收 我们按下换行是被scanner接收但并未添加到数据内 而服务器接收流收到的数据内//是没有换行符的 就会一直阻塞 所以我们要在数据后再加个\n//printWriter.write(requst+'\n');//或者直接使用println自带\nprintWriter.println(requst);//刷新缓冲区printWriter.flush();String response=scanner.next();System.out.println(response);}}finally {socket.close();}}

整体代码

package TestTCP;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 Test2 {private Socket socket=null;public Test2() throws IOException {socket=new Socket("127.0.0.1",8080);}public void start() throws IOException {try(InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()){while (true){Scanner scanner=new Scanner(inputStream);PrintWriter printWriter=new PrintWriter(outputStream);Scanner scanner1=new Scanner(System.in);System.out.println("输入数据>");String requst=scanner1.next();//因为这用流接收 我们按下换行是被scanner接收但并未添加到数据内 而服务器接收流收到的数据内//是没有换行符的 就会一直阻塞 所以我们要在数据后再加个\n//printWriter.write(requst+'\n');//或者直接使用println自带\nprintWriter.println(requst);//刷新缓冲区printWriter.flush();String response=scanner.next();System.out.println(response);}}finally {socket.close();}}public static void main(String[] args) throws IOException {Test2 t2=new Test2();t2.start();}
}

jconsole用来监控java线程

jconsole在路径 jdk/bin/jconsole.exe

例:

我们需要看util最后一局,可以看出线程是在next阻塞着。

相关文章:

Java网络通信TCP

目录 TCP两个核心类 服务端 1.用ServerSocker类创建对象并且手动指定端口号 2.accept阻塞连接服务端与客户端 3.给客户端提供处理业务方法 4.处理业务 整体代码 客户端 1.创建Socket对象,并连接服务端的ip与端口号 2.获取Socket流对象,写入数据…...

层级锁笔记

注意看test_hierarchy_lock函数&#xff1a;如果thread t2的不注释&#xff0c;就会报错。 这是因为层级锁 更强调单个线程内上锁的顺序。 线程t2已经获取了hmtx2&#xff0c;再试图获取hmtx1就会因为违反层级顺序而抛出异常。 #include <mutex> #include <thread&g…...

基于SpringBoot+Vue 的专家医院预约挂号系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…...

计算机基础专升本笔记十二-Excel常用快捷键大全

计算机基础专升本笔记十二-Excel常用快捷键大全 Excel常用快捷键 按键作用Ctrl 0隐藏列Ctrl 1设置单元格格式Ctrl 2添加或取消字体加粗Ctrl 3添加或取消字体倾斜Ctrl 4添加或取消下划线Ctrl 5添加或取消删除线Ctrl 6隐藏或显示图形Ctrl 7隐藏工具栏Ctrl 8隐藏或显示…...

制作耳机壳的UV树脂和塑料材质相比优势有哪些?

制作耳机壳的UV树脂相比塑料材质有以下优势&#xff1a; 高强度与耐磨性&#xff1a;UV树脂具有高强度和耐磨性&#xff0c;能够更好地保护耳机内部零件&#xff0c;延长耳机使用寿命。相比之下&#xff0c;塑料材质可能较易磨损或刮伤。耐高温&#xff1a;UV树脂具有较好的耐…...

JS(JavaScript)中如何实现,复选框checkbox多选功能

起始界面&#xff1a; 代码元素&#xff1a; <p><input type"checkbox" id"checkedAll"> 全选按钮</p><p><input type"checkbox" class"cl"> 选项1</p><p><input type"checkbox&qu…...

直接修改zynq petalinux编译出来的rootfs.cpio.gz文件内容

xilinx zynq petalinux 默认编译打包出的SPI flash烧写启动文件是BOOT.BIN&#xff0c;然而每次需要修改rootfs内的文件时都要重新build rootfs 然后再 package一次才能生成新的BOOT.bin文件&#xff0c;地球人都知道petalinux编译一次是很耗时间的&#xff0c;那么有没有什么简…...

什么是 Golang 类型断言

类型断言&#xff1a;用于检查某个接口是否包含某个具体类型&#xff0c;语法x.(T)&#xff0c;x是一个接口类型表达式&#xff0c;T是具体的类型&#xff0c;如果x包含的值可以被转换成T类型&#xff0c;则是ok 在Go语言中&#xff0c;任何类型的值都属于空接口类型。空接口类…...

mysql数据库root权限读写文件

如果没有shell&#xff0c;只有数据库权限的情况下&#xff1a; 1. udf 提权提示没有目录&#xff1a;使用数据流创建目录 1. select xxx into outfile C:\\phpstudy_pro\\Extensions\\MySQL5.5.29\\lib\::$INDEX_ALLOCATION;2. select xxx into outfile C:\\phpstudy_pro\…...

力扣爆刷第88天之hot100五连刷26-30

力扣爆刷第88天之hot100五连刷26-30 文章目录 力扣爆刷第88天之hot100五连刷26-30一、142. 环形链表 II二、21. 合并两个有序链表三、2. 两数相加四、19. 删除链表的倒数第 N 个结点五、24. 两两交换链表中的节点 一、142. 环形链表 II 题目链接&#xff1a;https://leetcode.…...

Ethersacn的交易数据是什么样的(2)

分析 Raw Transanction RLP&#xff08;Recursive Length Prefix&#xff09;是一种以太坊中用于序列化数据的编码方式。它被用于将各种数据结构转换为二进制格式&#xff0c;以便在以太坊中传输和存储。RLP 是一种递归的编码方式&#xff0c;允许对复杂的数据结构进行编码。所…...

学习Android的第二十二天

目录 Android ContextMenu 上下文菜单 ContextMenu 范例 参考文档 Android SubMenu 子菜单 范例 参考文档 Android PopupMenu 弹出菜单 范例 参考文档 Android ContextMenu 上下文菜单 在Android开发中&#xff0c;ContextMenu&#xff08;上下文菜单&#xff09;为…...

JavaScript——流程控制(程序结构)

JavaScript——流程控制&#xff08;程序结构&#xff09; 流程控制就是来控制我们的代码按照什么结构顺序来执行。更倾向于一种思想结构。 流程控制分为三大结构&#xff1a;顺序结构、分支结构、循环结构 1、顺序结构 ​ 代码从上往下依次执行&#xff0c;从A到B执行&#x…...

如何用ChatGPT+GEE+ENVI+Python进行高光谱,多光谱成像遥感数据处理?

原文链接&#xff1a;如何用ChatGPTGEEENVIPython进行高光谱&#xff0c;多光谱成像遥感数据处理&#xff1f; 第一&#xff1a;遥感科学 从摄影侦察到卫星图像 遥感的基本原理 遥感的典型应用 第二&#xff1a;ChatGPT ChatGPT可以做什么&#xff1f; ChatGPT演示使用 …...

AIGC工具( 7个 )

人工智能技术有好的一方面&#xff0c;又不好的地方&#xff0c;要区别对待&#xff0c;吸取精华&#xff0c;去其糟粕。目前市场上有很多AI大模型&#xff0c;可以支持聊天&#xff0c;写文稿&#xff0c;创作等&#xff0c;部分可以生成图片&#xff0c;以下是7个很不错的免费…...

学习Java的第一天

一、Java简介 Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称。由 James Gosling和同事们共同研发&#xff0c;并在 1995 年正式推出。 后来 Sun 公司被 Oracle &#xff08;甲骨文&#xff09;公司收购&#xff0c;Jav…...

【设计模式】工厂模式与抽象工厂模式

工厂方法 以图书馆管理系统为例&#xff0c;需要API提供查询不同专业分类的书目列表&#xff0c;一般实现&#xff0c; class LibraryManager { public:LibraryManager() {}//按专业分类查询BookList Query(Type type) {if(type TA) {return ...;} else if (type TB) {} el…...

使用plasmo框架开发浏览器插件,注入contents脚本和给页面添加UI组件

plasmo&#xff1a;GitHub - PlasmoHQ/plasmo: &#x1f9e9; The Browser Extension Framework plasmo是一个开发浏览器插件的框架&#xff0c;支持使用react和vue等技术&#xff0c;而且不用手动管理manifest.json文件&#xff0c;框架会根据你在框架中的使用&#xff0c;自…...

python并发 惰性处理大型数据集

惰性计算是一种编程策略&#xff0c;它使得程序在何时执行计算的决定推迟到需要结果时才进行。这种策略的好处在于&#xff0c;它允许程序处理大规模数据或者需要大量计算的任务时节省内存和计算资源。 举例来说&#xff0c;当我们调用 Python 中的 range() 函数时&#xff0c…...

Docker将本地的镜像上传到私有仓库

使用register镜像创建私有仓库 [rootopenEuler-node1 ~]# docker run --restartalways -d -p 5000:5000 -v /opt/data/regostry:/var/lib/registry registry:2[rootopenEuler-node1 ~]# docker images REPOSITORY TAG IMAGE…...

Qwen3Guard-Gen-8B真实案例:如何用AI模型自动拦截不当言论

Qwen3Guard-Gen-8B真实案例&#xff1a;如何用AI模型自动拦截不当言论 1. 引言&#xff1a;内容安全的新挑战 在数字内容爆炸式增长的今天&#xff0c;各类平台都面临着内容审核的巨大压力。传统的关键词过滤和规则匹配系统已经难以应对日益复杂的网络环境&#xff0c;特别是…...

数字记忆策展:WeChatMsg与数据主权时代的个人记忆管理

数字记忆策展&#xff1a;WeChatMsg与数据主权时代的个人记忆管理 【免费下载链接】WeChatMsg 提取微信聊天记录&#xff0c;将其导出成HTML、Word、CSV文档永久保存&#xff0c;对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeCha…...

Path of Building:流放之路构筑规划的精准导航工具

Path of Building&#xff1a;流放之路构筑规划的精准导航工具 【免费下载链接】PathOfBuilding Offline build planner for Path of Exile. 项目地址: https://gitcode.com/gh_mirrors/pat/PathOfBuilding 在《流放之路》复杂多变的角色构建世界中&#xff0c;Path of …...

29、【Agent】【OpenCode】模型配置(OpenCode Zen)(二)

【声明】本博客所有内容均为个人业余时间创作&#xff0c;所述技术案例均来自公开开源项目&#xff08;如Github&#xff0c;Apache基金会&#xff09;&#xff0c;不涉及任何企业机密或未公开技术&#xff0c;如有侵权请联系删除 背景 上篇 blog 【Agent】【OpenCode】模型配…...

深入探索UEFI Shell中的dh命令:高效检测系统Protocol安装状态

1. UEFI Shell与dh命令基础认知 刚接触UEFI开发时&#xff0c;我经常遇到这样的困扰&#xff1a;某个驱动明明编译通过了&#xff0c;运行时却提示"Protocol not found"。传统做法是在代码里插入调试语句&#xff0c;用gBS->LocateProtocol检查Protocol状态&#…...

RTX4090D大模型推理专用镜像体验:Qwen-Image预装环境,一键启动图文对话

RTX4090D大模型推理专用镜像体验&#xff1a;Qwen-Image预装环境&#xff0c;一键启动图文对话 1. 镜像概述与核心优势 1.1 为什么选择专用镜像 在本地部署大语言模型时&#xff0c;环境配置往往是最耗时的环节。以Qwen-VL这样的视觉语言模型为例&#xff0c;需要处理CUDA版…...

GD32F4系列定时器正交译码器实战:用STM32CubeMX的思路配置编码器接口

GD32F4定时器正交译码器实战&#xff1a;从STM32CubeMX到GD32的平滑迁移指南 在工业控制、机器人运动检测等领域&#xff0c;正交编码器作为位置和速度反馈的关键传感器&#xff0c;其信号处理能力直接影响系统精度。对于熟悉STM32生态的开发者而言&#xff0c;当项目需要迁移至…...

如何快速使用网站历史查看器:新手完整入门教程

如何快速使用网站历史查看器&#xff1a;新手完整入门教程 【免费下载链接】wayback-machine-webextension A web browser extension for Chrome, Firefox, Edge, and Safari 14. 项目地址: https://gitcode.com/gh_mirrors/wa/wayback-machine-webextension 你是否曾经…...

别再只用箱线图了!用Python的PtitPrince库5分钟搞定雨云图,数据分布一目了然

数据可视化新选择&#xff1a;用PtitPrince打造专业级雨云图 在数据分析的世界里&#xff0c;可视化工具的选择往往决定了我们能否准确传达数据背后的故事。传统箱线图虽然简洁&#xff0c;却隐藏了太多细节&#xff1b;提琴图展示了分布形态&#xff0c;却丢失了原始数据点。这…...

解锁AI创作自由:ComfyUI节点式工作流从入门到精通

解锁AI创作自由&#xff1a;ComfyUI节点式工作流从入门到精通 【免费下载链接】ComfyUI 最强大且模块化的具有图形/节点界面的稳定扩散GUI。 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI 你是否遇到过这样的困境&#xff1a;想要调整AI生成图像的某个细节…...