【JavaEE】网络编程——TCP

在这里插入图片描述
🤡🤡🤡个人主页🤡🤡🤡
🤡🤡🤡JavaEE专栏🤡🤡🤡

文章目录

  • 前言
  • 1.网络编程套接字
    • 1.1流式套接字(TCP)
      • 1.1.1特点
      • 1.1.2编码
        • 1.1.2.1ServerSocket
        • 1.1.2.2Socket
        • 1.1.2.3实现一个TCP(7*24)回显服务器
        • 1.1.2.4实现一个TCP的客户端
        • 1.1.2.5实现一个TCP字典翻译服务器

前言

网络编程的目的是为了跨主机通信,socket==》操作系统提供的网络编程的API就称为"socket"API

1.网络编程套接字

TCP和UDP都是传输层协议,都是给应用层提供服务的,由于这两个协议特点差异非常打,因此我们就需要两套API来分别表示。

1.1流式套接字(TCP)

1.1.1特点

  1. 有连接:在数据传输开始前,需要通信双方建立一个专用的通道,数据传输完成后再关闭连接,好比打电话,需要双方都接通才可以对话
  2. 可靠传输:在传输数据的时候,尽可能的将数据传输到达对方,并不是100%
  3. 面向字节流:面向对象是字节,在读写的操作会非常灵活。
  4. 全双工:一条链路中,能够进行双向通信。

1.1.2编码

TCP中的socket API重点是两个类:ServerSocket和Socket。

1.1.2.1ServerSocket

ServerSocket这个类主要是用于TCP的服务器的,里面有一个非常重要的方法accept,这个方法主要是让服务器与客户端建立连接的方法,没有建立连接是无法让服务器与客户端双方互相通信。

1.1.2.2Socket

Socket这个类是既可以用于服务器中也可以用于客户端中,这个类主要是以字节的形式将数据存储和传输的,所以这个类中提供的两种方法可以类比文件操作中的方法,这个类提供getInputStream()和getOutputStream()
前者是相当于文件操作中的读操作,后者类比于写操作,只是这里的操作对象换成了服务器与客户端了。

1.1.2.3实现一个TCP(7*24)回显服务器

在这里由于getInputStream()数据都是以字节的形式存在和传输的,但在处理响应的时候会转化为字符串的形式,为了不这么麻烦的去转化,我们就用Scanner来作为读操作,将getInputStream实现的对象放入Scanner构造方法中,让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("服务器启动!!!");//将服务器与客户端进行连接,连接成功返回一个Socket对象,后续服务器对客户端的操作都基于这个对象while(true) {Socket clientSocket = serverSocket.accept();//创建一个方法来操作每一个客户端与服务器的联系processConnection(clientSocket);}}public void processConnection(Socket clienSocket) throws IOException {//打印一个客户端上线的日志System.out.printf("[%s:%d]客户端上线!\n",clienSocket.getInetAddress(),clienSocket.getPort());//1.接收客户端发送过来的信息和并解析try(InputStream inputStream = clienSocket.getInputStream();OutputStream outputStream = clienSocket.getOutputStream()) {//接收客户端发送过来的请求并解析(相当于从客户端读到服务器),用到Scanner的原因是由于InputStream读取的数据是字节的形式,//后续处理数据的时候还是要将数据从字节形式转化为字符串,而Scanner内部可以帮我们直接转化。Scanner scanner = new Scanner(inputStream);//由于需要处理客户端不断发送过来的请求,我们就需要一个while循环while(true) {//处理客户端那边不发送请求的情况if(!scanner.hasNext()) {System.out.printf("[%s:%d]客户端下线!\n",clienSocket.getInetAddress(),clienSocket.getPort());break;}//将从客户端接收过来的数据赋值到request中,为之后处理数据做铺垫//这里的scanner.next()需要读到空白符才会停止,所以为了区分每一份的应用层的数据报,所以我们可以在客户端手动添加空白符,//来控制每一份的应用层数据报String request = scanner.next();//2.计算响应,由于这是一个回显服务器,所以我们呢不需要对响应做处理,请求什么就返回什么响应String response = process(request);//3.将计算好的响应传回客户端(相当与将数据写回客户端)outputStream.write(response.getBytes(),0,response.getBytes().length);//4.打印服务器日志System.out.printf("[%s:%d]res = %s,resp = %s\n",clienSocket.getInetAddress(),clienSocket.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}finally {clienSocket.close();}}private String process(String request) {return request + "\n";}public static void main(String[] args) throws IOException {tcpEchoServer server = new tcpEchoServer(9999);server.start();}
}

在这里插入图片描述
程序走到这里有两种情况:

  1. 服务器与客户端双方之间的连接还在,但是客户端并没有发送请求,则会在此处进行阻塞,直到客户端发送请求过来,才会解除阻塞
  2. 服务器与客户端双方之间的连接已经断开了,那么直接就执行了if中的语句
    关于if中的scanner怎么判断连接存在还是不存在的情况,scanner是无法判断的,scnner只有阻塞作用,判断连接是否存在是scoket来判断的。
1.1.2.4实现一个TCP的客户端
public class tcpEchoClient {public Socket socket = null;public tcpEchoClient(String serverIp,int serverProt) throws IOException {socket = new Socket(serverIp,serverProt);}public void start() throws IOException {//打印日志System.out.println("客户端启动!");//1.从控制台读取Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()){Scanner scannerNetwork = new Scanner(inputStream);while(true) {System.out.println("请输入你的请求:");String request = scanner.next();//与服务器规定的规则相对应request += "\n";//2.发送请求到服务器(写入服务器中)outputStream.write(request.getBytes());//3.接收从服务器发送过来的响应(从服务器将响应读入客户端)if(!scannerNetwork.hasNext()) {break;}String response = scannerNetwork.next();//4.将回应打印到控制台System.out.println(response);}}}public static void main(String[] args) throws IOException {tcpEchoClient client = new tcpEchoClient("127.0.0.1",9999);client.start();}
}

上述的服务器还是存在一些问题的,比如:无法处理多个客户端同时来访问服务器,解决这个问题可以使用多线程让一个主线程来创建多个服务器与客户端连接的对象,然后再用其他线程来给客户端提供服务。

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 pool = Executors.newCachedThreadPool();//将服务器与客户端进行连接,连接成功返回一个Socket对象,后续服务器对客户端的操作都基于这个对象while(true) {Socket clientSocket = serverSocket.accept();pool.submit(new Runnable() {@Overridepublic void run() {try {processConnection(clientSocket);} catch (IOException e) {throw new RuntimeException(e);}}});}}public void processConnection(Socket clienSocket) throws IOException {//打印一个客户端上线的日志System.out.printf("[%s:%d]客户端上线!\n",clienSocket.getInetAddress(),clienSocket.getPort());//1.接收客户端发送过来的信息和并解析try(InputStream inputStream = clienSocket.getInputStream();OutputStream outputStream = clienSocket.getOutputStream()) {//接收客户端发送过来的请求并解析(相当于从客户端读到服务器),用到Scanner的原因是由于InputStream读取的数据是字节的形式,//后续处理数据的时候还是要将数据从字节形式转化为字符串,而Scanner内部可以帮我们直接转化。Scanner scanner = new Scanner(inputStream);//由于需要处理客户端不断发送过来的请求,我们就需要一个while循环while(true) {//处理客户端那边不发送请求的情况if(!scanner.hasNext()) {System.out.printf("[%s:%d]客户端下线!\n",clienSocket.getInetAddress(),clienSocket.getPort());break;}//将从客户端接收过来的数据赋值到request中,为之后处理数据做铺垫//这里的scanner.next()需要读到空白符才会停止,所以为了区分每一份的应用层的数据报,所以我们可以在客户端手动添加空白符,//来控制每一份的应用层数据报String request = scanner.next();//2.计算响应,由于这是一个回显服务器,所以我们呢不需要对响应做处理,请求什么就返回什么响应String response = process(request);//3.将计算好的响应传回客户端(相当与将数据写回客户端)outputStream.write(response.getBytes(),0,response.getBytes().length);//4.打印服务器日志System.out.printf("[%s:%d]res = %s,resp = %s\n",clienSocket.getInetAddress(),clienSocket.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}finally {clienSocket.close();}}private String process(String request) {return request + "\n";}public static void main(String[] args) throws IOException {tcpEchoServer server = new tcpEchoServer(9999);server.start();}
}
1.1.2.5实现一个TCP字典翻译服务器
public class tcpDictServer extends tcpEchoServer{HashMap<String,String> map = null;public tcpDictServer(int port) throws IOException {super(port);map = new HashMap<>();map.put("server","服务\n");map.put("client","客户端\n");map.put("cat","🐱\n");map.put("dog","🐕\n");map.put("pig","🐖\n");}@Overridepublic String process(String request) {return map.getOrDefault(request,"该词汇没有查询到");}public static void main(String[] args) throws IOException {tcpDictServer tcpDictServer = new tcpDictServer(9999);tcpDictServer.start();}
}

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

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

相关文章

华为USG6000V防火墙v1

目录 一、实验拓扑图 二、要求 三、IP地址规划 四、实验配置 1&#x1f923;防火墙FW1web服务配置 2.网络配置 要求1&#xff1a;DMZ区内的服务器&#xff0c;办公区仅能在办公时间内(9:00-18:00)可以访问&#xff0c;生产区的设备全天可以访问 要求2&#xff1a;生产区不…

电影《头脑特工队2》观后感

上周看了电影《头脑特工队2》&#xff0c;整体是非常不错的&#xff0c;一个大脑中&#xff0c;想象的世界。 &#xff08;1&#xff09;人格-多元政体理论 记得前几年是看过《头脑特工队1》的&#xff0c;当时电影是非常出名的&#xff0c;当时有很多研究理论&#xff0c;都…

【练习】分治--归并排序

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;算法(Java)&#x1f4d5;格言&#xff1a;吾愚多不敏&#xff0c;而愿加学欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 归并排序 代码实现 交易逆序对的总数 题目描述 ​编辑 题解 代码实…

JAVA从入门到精通之入门初阶(二)

1. 自动类型转换 自动类型转换&#xff1a;类型范围小的变量可以赋值给类型范围大的变量 byte->int public class java_7_10 {public static void main(String[] args) {//自动类型转换//类型范围小的变量可以赋值给类型范围大的变量 byte->intbyte a 12;int b a;//自动…

C语言 ——— 输入两个正整数,求出最小公倍数

目录 何为最小公倍数 题目要求 代码实现 方法一&#xff1a;暴力求解法&#xff08;不推荐&#xff09; 方法二&#xff1a;递乘试摸法&#xff08;推荐&#xff09; 何为最小公倍数 最小公倍数是指两个或者多个正整数&#xff08;除了0以外&#xff09;的最小的公共倍数…

【LeetCode】205. 同构字符串

认真地分类讨论&#xff0c;评判复杂度&#xff0c;再决定是否要写代码执行。整套流程干净利落&#xff0c;不存在主观臆想&#xff0c;也不会有对事实结果计算的巨大偏差。 1. 题目 2. 分析 这里提供一版可以解题的思路。 定义两个词典&#xff0c;这两个词典分别记录s字符串…

DHC2-2多时段电子式时间继电器 带底座 约瑟JOSEF

DHC2多时段电子式时间继电器 DHC2-H多时段电子式时间继电器 DHC2-1多时段电子式时间继电器 DHC2-2多时段电子式时间继电器 DHC2-3多时段电子式时间继电器 一、特点 超小型面板尺寸DIN 36X36mm(DHC1)、DIN 48X48m(DHC2) 有延时吸合、延时释放、等周期循环三种规格 可替代…

kibana连接elasticsearch(版本8.11.3)

前言 elasticsearch在8版本之后就出现了很大变化&#xff0c;由于kibana版本需要需elasticsearch进行版本对象&#xff0c;kibana连接方式也出现了很大变化。我在这里记录下自己的踩坑记录。 服务部署 本文中的服务都是在docker环境中部署的。其中elasticsearch版本和kibana版…

5G-A通感融合赋能低空经济-RedCap芯片在无人机中的应用

1. 引言 随着低空经济的迅速崛起&#xff0c;无人机在物流、巡检、农业等多个领域的应用日益广泛。低空飞行器的高效、安全通信成为制约低空经济发展的关键技术瓶颈。5G-A通感一体化技术通过整合通信与感知功能&#xff0c;为低空网络提供了强大的技术支持。本文探讨了5G-A通感…

OpenCV 寻找棋盘格角点及绘制

目录 一、概念 二、代码 2.1实现步骤 2.2完整代码 三、实现效果 一、概念 寻找棋盘格角点&#xff08;Checkerboard Corners&#xff09;是计算机视觉中相机标定&#xff08;Camera Calibration&#xff09;过程的重要步骤。 OpenCV 提供了函数 cv2.findChessboardCorners…

什么? CSS 将支持 if() 函数了?

CSS Working Group 简称 CSSWG, 在近期的会议中决定将 if() 添加到 CSS Values Module Level 5 中。 详情可见&#xff1a;css-meeting-bot 、[css-values] if() function 当我看到这个消息的时候&#xff0c;心中直呼这很逆天了&#xff0c;我们知道像 less 这些 css 这些预…

用Speedtest-Tracker跟踪上网速度(续)

什么是 Speedtest Tracker ? Speedtest Tracker 是一款自托管互联网性能跟踪应用程序&#xff0c;可针对 Ookla 的 Speedtest 服务运行速度测试检查。 之前老苏介绍的另一个 https://github.com/henrywhitaker3/Speedtest-Tracker 已被放弃。现在这个是积极维护的替代品&#…

STM32编写代码之嵌入式常用位操作

在单片机编程的过程中&#xff0c;经常会遇到位操作进行赋值&#xff0c;例如 //程序1 int a 0,b 0x5b,c 0; //1 for (i 0; i < 8; i ) { //2a b & (0x80 >> i)); //3 c | (0x80 >> i); //4 } 这些位操作是什么意思呢&#xff1f…

GuLi商城-商品服务-API-品牌管理-JSR303自定义校验注解

自定义注解规则: 可以参考@NotNull注解 package com.nanjing.common.valid;import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target;i…

跨域解决方案

跨域 当发起请求的协议号、域名、端口号中有一个不一样时就会导致跨域 跨域解决方案 分为两个方面&#xff0c;是否可以修改服务器端。 可以修改服务器端&#xff1a;cors方案、jsonp方案 不可以修改服务器端&#xff1a; 使用代理&#xff1a; 因为跨域主要是针对浏览器…

T113-i系统启动速度优化方案

背景: 硬件:T113-i + emmc 软件:uboot2018 + linux5.4 + QT应用 分支:longan 问题: 全志T113-i的官方系统软件编译出的固件,开机启动时间10多秒,启动时间太长,远远超过行业内linux系统的开机速度,需要进一步优化。 T113-i 优化后启动速度实测数据 启动阶段启动时间(…

Fastgpt本地使用Docker Compose 快速部署

使用 Docker Compose 快速部署 FastGPT 部署架构图 MongoDB:用于存储除了向量外的各类数据 PostgreSQL/Milvus:存储向量数据 OneAPI: 聚合各类 AI API,支持多模型调用 (任何模型问题,先自行通过 OneAPI 测试校验) 推荐配置 PgVector版本 体验测试首选 环境最低配置(单…

MySql性能调优04-[MySql事务与锁机制原理]

MySql事务与锁机制原理 从undo与redo日志&#xff0c;理解事务底层ACID底层原理事务四大隔离级别事务底层锁机制和MVCC并发优化机制串行化底层实现机制读已提交和可重复读底层实现MVCC机制详解脏写问题(重要)读已提交&#xff1f;实现机制 BufferPool缓存与redo日志是如何提升事…

海康相机GrabImage

#include <stdio.h> #include <Windows.h> #include <process.h> #include <conio.h> #include "MvCameraControl.h"bool g_bExit false;// ch:等待按键输入 | en:Wait for key press void WaitForKeyPress(void) {while(!_kbhit()){Sleep(…

6.S081的Lab学习——Lab11: Network

文章目录 前言Network提示&#xff1a;实现e1000_transmit的一些提示&#xff1a;实现e1000_recv的一些提示&#xff1a; 解析 总结 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招。打算尝试6.S081&#xff0c;将它的Lab逐一实现&#xff0c;并记录期间心酸历程。 代码下…