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阻塞着。

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

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

相关文章

Linux: Network: socket: sendto 如果返回0,是否一定代表发送成功?

最近遇到一个问题,虽然应用层使用的系统调用send已经返回成功,而且没有错误日志产生,也没有errno的设置。那是不是代表一定是没有问题?从抓包的结果看,虽然上层应用已经显示发出去,但是实际抓包的时候&…

被曝隐瞒添加剂、夸大产品功效,东方甄选再陷选品风波

号称专注为客户细心甄选好物的东方甄选((HK:01797)),又摊上事儿了。 近日,海关总署发布公告称,美国饮料生产企业JERRY&SONS PHARMACEUTICAL INC在申请注册时提供了虚假材料,且未…

C2_W2_Assignment_吴恩达_中英_Pytorch

Neural Networks for Handwritten Digit Recognition, Multiclass In this exercise, you will use a neural network to recognize the hand-written digits 0-9. 在本次练习中,您将使用神经网络来识别0-9的手写数字。 Outline 1 - Packages 2 - ReLU Activatio…

c语言经典测试题9

1.题1 #include <stdio.h> int main() { int i 1; sizeof(i); printf("%d\n", i); return 0; } 上述代码运行结果是什么呢&#xff1f; 我们来分析一下&#xff1a;其实这题的难点就是sizeof操作后i的结果是否会改变&#xff0c;首先我们创建了一个整型i&a…

分布式基础 --- Leader election

分布式基础 --- Leader election 为什么需要leader electionRing electionBully Algorithm 为什么需要leader election 在一组集群中, 需要选出一个leader来承担一些特别的任务, 比如 协调和控制系统操作&#xff1a;领导者负责协调和控制整个分布式系统的操作。它可以接收和处…

one4all 排坑记录

one4all 排坑记录 任务踩坑回顾动作踩坑动作踩坑动作新一步测试Habitat-sim 测试habitat-lab继续ONE4ALL 任务 看了《One-4-All: Neural Potential Fields for Embodied Navigation》这篇论文&#xff0c;感觉挺有意思&#xff0c;他也开源了代码。视觉语言导航是我一直想做的…

windows上elasticsearch的ik分词器的安装

下载 下载地址 在elasticsearch下的plugins文件夹下创建ik的文件夹 下载的ik压缩包解压到plugins/ik 重启elasticsearch 验证 http://ip:9200/_cat/plugins

SpringBoot3-核心原理

1. 事件和监听器 1. 生命周期监听 场景&#xff1a;监听应用的生命周期 1. 监听器-SpringApplicationRunListener 自定义SpringApplicationRunListener来监听事件&#xff1b; 编写SpringApplicationRunListener 实现类在 META-INF/spring.factories 中配置 org.springfram…

【蓝桥杯】错误票据

今天是2024年3月1号&#xff0c;蓝桥杯比赛还有一个月的时间&#xff0c;虽说自己不指望拿奖吧&#xff0c;但是还是有些莫i名的焦虑&#xff0c;这道题目都做不出来&#xff0c;感觉自己真的有点菜啊&#xff01;但是还好啦&#xff0c;我觉得是因为我没有题感&#xff0c;慢慢…

spring boot 整合 minio存储 【使用篇】

导入依赖 <!--minio--><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.0.3</version></dependency> yml配置&#xff08;默认配置&#xff09; max-file-size: 200MB 设置文件最大…

华为od机试C卷-开源项目热度榜单

1、题目描述 某个开源社区希望将最近热度比较高的开源项目出一个榜单&#xff0c;推荐给社区里面的开发者。 对于每个开源项目&#xff0c;开发者可以进行关注(watch)、收藏(star)、fork、提issue、提交合并请求(MR)等。 数据库里面统计了每个开源项目关注、收藏、fork、issue…

微服务API网关---APISIX

最近在做微服务调研&#xff0c;看到了apisix这个网关&#xff0c;于是进行了初步了解一下。 微服务是指&#xff0c;将大型应用分解成多个独立的组件&#xff0c;其中每个组件都各自的负责对应项目。 系统的架构大致经历了&#xff1a;单体应用架构–> SOA架构 -->微服务…

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 附录D 关于TCP并发连接的几个思考题与试验

前几天作者在新浪微博上出了两道有关TCP的思考题&#xff0c;引发了一场讨论&#xff08;http://weibo.com/1701018393/eCuxDrtaONn&#xff09;。 第一道初级题目是&#xff1a;有一台机器&#xff0c;它有一个IP&#xff0c;上面运行了一个TCP服务程序&#xff0c;程序只侦听…

StarRocks实战——松果出行实时数仓实践

目录 一、背景 二、松果出行实时OLAP的演进 2.1 实时数仓1.0的架构 2.2 实时数仓2.0的架构 2.3 实时数仓3.0的架构 三、StarRocks 的引入 四、StarRocks在松果出行的应用 4.1 在订单业务中的应用 4.2 在车辆方向的应用 4.3 StarRocks “极速统一” 落地 4.4 StarRoc…

分布式ID生成系统之雪花算法详解

在当今的云计算和微服务架构盛行的时代&#xff0c;分布式系统已成为软件开发的重要组成部分。随着系统规模的扩大和业务的复杂化&#xff0c;对数据一致性和唯一性的要求也越来越高&#xff0c;尤其是在全局唯一标识符&#xff08;ID&#xff09;的生成上。因此&#xff0c;分…

yolov5训练太慢的解决方案

问题原因 训练太慢大多是因为没有安装CUDA和pytorch&#xff0c;导致的只有cpu在跑&#xff0c;显卡没跑 这就是很典型的。 解决方案 第一步&#xff1a;安装CUDA 在本机上面安装CUDA,记住只有N卡可以安装&#xff0c;一开始的电脑是自带CUDA的。 如果不是自带的CUDA&…

求数字的每一位之和

求数字的每一位之和 题目描述&#xff1a;解法思路&#xff1a;解法代码&#xff1a;运行结果&#xff1a; 题目描述&#xff1a; 输入一个整数m&#xff0c;求这个整数m的每⼀位之和&#xff0c;并打印。 测试1&#xff1a; 输⼊&#xff1a;1234 输出&#xff1a;10 测试2&…

土壤侵蚀量化评估

根据之前的文章,已经算出了R、K、LS、C、P 现在计算土壤侵蚀,将几个前期制作好的因子的TIFF文件,用栅格计算器相乘 发现局部地区存在轻度侵蚀,大部分区域是微度侵蚀 然后对比了一下范围 其中的几个因子都在文献范围内,说明计算结果并未出错,可能就是研究区正常范围和结…

6020一拖二快充线:手机充电的革命性创新

在快节奏的现代生活中&#xff0c;手机已不仅仅是一个通讯工具&#xff0c;更是我们工作、学习和娱乐的得力助手。然而&#xff0c;手机的电量问题一直是困扰着我们的难题。为了解决这个问题&#xff0c;市场上出现了一种名为“一拖二快充线”的充电设备&#xff0c;它不仅具备…

八. 实战:CUDA-BEVFusion部署分析-分析BEVFusion中各个ONNX

目录 前言0. 简述1. camera.backbone.onnx(fp16)2. camera.backbone.onnx(int8)3. camera.vtransform.onnx(fp16)4. fuser.onnx(fp16)5. fuser.onnx(int8)6. lidar.backbone.xyz.onnx7. head.bbox.onnx(fp16)总结下载链接参考 前言 自动驾驶之心推出的《CUDA与TensorRT部署实战…