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

JAVAEE初阶相关内容第十六弹--网络编程

写在前

这一节的内容首先是对十五弹(UDP回显服务器)进行简单的改进,在这基础上开始介绍TCP流套接字编程。

目录

写在前

1.改进回显服务器

1.1完整代码实现

1.2运行输出结果

2.TCP流套接字编程

2.1ServerSocketAPI

2.2SocketAPI

3.TCP版本的回显服务器

3.1代码实现

3.1.1服务器端完整代码

3.1.2客户端完成代码

3.2TCP中的长短连接

3.3解决C10M问题


1.改进回显服务器

上一节中的回显服务器,缺少业务逻辑,这里我们对代码进行改进,实现一个查词典的功能

1.1完整代码实现

这里需要的是需要重写一下process方法!

package network;import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;/*** Created with IntelliJ IDEA.* Description:* User: 苏西西* Date: 2023-10-19* Time: 21:55*/
//对于DictServer来说,和EchoServer相比大部分东西都是一样的,继承复用原来的代码
//主要是根据请求计算响应这个步骤不太一样
public class UdpDictServer extends UdpEchoServer{private Map<String,String> dict = new HashMap<>();public UdpDictServer(int port) throws SocketException {super(port);//给这个dict设置一下内容dict.put("cat","小猫");dict.put("dog","小狗");dict.put("pig","zyt");//可以无限多设置}@Overridepublic String process(String request){//查词典return dict.getOrDefault(request,"查不到!");}public static void main(String[] args) throws IOException {UdpDictServer server = new UdpDictServer(4000);server.start();}
}

1.2运行输出结果

2.TCP流套接字编程

TCP并不需要一个类来表示“TCP”数据报。

TCP不是以数据报为单位进行传输的,是以字节的方式,流式传输的。

2.1ServerSocketAPI

ServerSocket 专门给服务器使用的Socket对象。

ServerSocket构造方法
方法签名方法说明

ServerSocket(int port)

这里的port指的是服务器要绑定的端口。

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

这里,accept() 类比于接电话;返回一个服务端Socket对象:接电话后会返回一个Socket对象,通过这个socket对象和客户端进行沟通。

2.2SocketAPI

Socket 既会给客户端使用,也会给服务器使用。

在服务器这边,是由accept返回的;在客户端这边,代码构造的时候指定一个IP和端口号(此处值指的是服务器的IP和端口),有了这个信息就可以和服务器建立连接了。

Socket构造方法
方法签名方法说明
Socket(String host,int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接。
Socket方法
方法签名方法说明
InetAddress getInetAddress()返回套接字所连接的地址

InputStream getInputStream()

返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

进一步通过Socket对象,获取到内部的流对象,借助流对象来进行发送/接收。

3.TCP版本的回显服务器

3.1代码实现

3.1.1服务器端完整代码

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;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){//使用这个clientSocket和具体的客户端进行交流。Socket clientSocket = serverSocket.accept();processConnection(clientSocket);}}//使用这个放方法来处理一个连接。//这一个连接对应到一个客户端,但是这里可能会涉及到多次交互。private void processConnection(Socket clientSocket) {System.out.printf("[%s:%d] 客户端上线\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());//基于上述socket对象和客户端进行通信try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {//由于要处理多个请求和响应,也是使用循环来进行的while (true){//1.读取请求Scanner scanner = new Scanner(inputStream);if (!scanner.hasNext()){//如果没有下一个说明读完了,客户端关闭了连接System.out.printf("[%s:%d] 客户端下线\n!",clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}//注意:此处使用的next是一直读取到换行符/空格/其他空白符结束//最终返回结果里不包含上述空白符String request = scanner.next();//2.根据请求构造响应String response = process(request);//3.返回响应结果//对于OutputStream 没有write String这个功能,可以把String里的字节数组拿出来,进行写入;//也可以用字符流来转换一下PrintWriter printWriter = new PrintWriter(outputStream);//此处使用println来写入,让结果中带有一个\n换行,方便对端(接收端)接收解析printWriter.println(response);//flush用来冲刷缓冲区,保证当前写入的数据确实发送出去了printWriter.flush();//打印一个日志System.out.printf("[%s:%d] req:%s;resp:%s\n",clientSocket.getInetAddress().toString(),clientSocket.getPort(),request,response);}} catch (IOException e) {e.printStackTrace();}finally {//更合适的做法是将close放到finally里面,保证close()一定会被执行到try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {TcpEchoServer server = new TcpEchoServer(1111);server.start();}}

这里的accept() 效果是“接收连接”,前提是得有客户端来建立连接。客户端在构造Socket对象的时候就会指定服务器的IP和端口,如果没有客户端来连接,此时的accept就会阻塞。


TCP socket里面涉及两种socket对象。

这个代码中,用到了一个clientSocket,此时任意一个客户端连上来都会返回/创建一个Socket对象。(Socket就是文件)每次创建一个clientSocket对象就要占用一个文件描述符表的位置。

因此在使用完毕之后,就需要进行“释放”。

在前面的记录中,socket都没有释放,一方面这些socket生命周期更长(跟随整个程序),另一方面这些socket也不多,固定数量。

但是此处的clientSocket数量多,每个客户端都有一个,生命周期也更短。

3.1.2客户端完成代码

package network;import com.sun.xml.internal.ws.policy.privateutil.PolicyUtils;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 TcpEchoClient {//当前这里的socket既给服务器用,又给客户端用,private Socket socket = null;public TcpEchoClient(String serverIp,int serverPort) throws IOException {//Socket构造方法能够识别点分十进制格式的ip地址,比DatagramPacket更方便//new这个对象的同时,就会进行Tcp连接操作socket = new Socket(serverIp,serverPort);}public void start(){System.out.println("客户端启动!");Scanner scanner = new Scanner(System.in);try(InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {while (true){//1.先从键盘上读取用户输入的内容System.out.print(" >");String request  = scanner.next();if(request.equals("exit")){System.out.println("goodbye");break;}//2.把读到的内容构造成请求,发送给服务器PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(request);//此处加上flush,保证我们的数据确实发送出去了printWriter.flush();//3.读取服务器的响应,Scanner respScanner = new Scanner(inputStream);String response = respScanner.next();//4.把响应的内容给显示到界面上System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient client = new TcpEchoClient("127.0.0.1",1111);client.start();}
}

这个对象的构造过程,就是触发TCP建立连接的过程(打电话就开始拨号了),如果客户端没有这个代码,服务器就会在accept这里阻塞,无法产生出clientSocket了。

outputSteam相当于是​对应着一个文件描述符表(socket文件),通过outputStream就可以往这个文件描述符表中写数据。

outputStream自身的方法不便写字符串,把这个流转换一下,用一个PrintWrite对象来表示(对应的文件描述符表还是同一个)

使用PrintWrite写和OutputStream写,是往同一个地方写,只不过写的过程更方便了。

3.2TCP中的长短连接

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

(1)短连接:客户端每次给服务器发消息,先建立连接,发送请求,读取响应,关闭连接。下次再发送,则重新建立加连接。

(2)长连接:客户端,建立连接之后,连接不着急断开,然后再发送请求,读取响应​​​​;若干轮之后,客户端确实短时间内不再需要这个连接了,此时就断开。

服务器这里的开发很少有不用多线程的情况(当然也有用多进程的)。

这里就可以对代码进行改进:

使用多线程版本处理程序,最大的问题就是可能会涉及到频繁的申请释放线程。

在多线程的基础上,使用线程池进行代码编写。

但是如果客户端非常多,而且客户端还迟迟不断开的高压,就回导致机器上会有很多线程。此时就就会提起一种方法:增加机器。但是这就意味着需要增加成本,需要多花钱,这里的问题又被称为是C10M问题。

3.3解决C10M问题

C10K问题:单机处理1W个客户端。

C10M问题,单机处理1kw个客户端(针对多线程的版本,最大的问题就是机器承担不了这么大的线程开销,是否有办法一个线程,处理很多个客户端连接?)

IO多路复用/IO多路转接

给这个线程安排个集合,这个集合就放了一堆连接,线程就负责监听这个集合,这里的哪个连接有数据来,线程就处理哪个连接。虽然连接有很多,但是这些连接的请求并非严格意义的同时,总还是有先后的。

在操作系统中提供了一些原生的API select、poll、epoll 在Java中提供了一组NIO 这样 类,就封装了上述多路复用的API。

这一节和前一节的内容主要介绍的就是Udp和TcpSocket编程,需要注意的是,关于有无连接、面向字节流还是数据报以及全双工与否,这些特点在代码中都是有体现的。关于时候是可靠传输这一特点是隐藏在TCP背后,从代码的角度是感受不到的。TCP诞生的初心也就是为了解决可靠传输的问题。

下一部分将介绍网络原理知识的相关内容。

继续加油哦!

相关文章:

JAVAEE初阶相关内容第十六弹--网络编程

写在前 这一节的内容首先是对十五弹&#xff08;UDP回显服务器&#xff09;进行简单的改进&#xff0c;在这基础上开始介绍TCP流套接字编程。 目录 写在前 1.改进回显服务器 1.1完整代码实现 1.2运行输出结果 2.TCP流套接字编程 2.1ServerSocketAPI 2.2SocketAPI 3.TC…...

Python---练习:使用for循环嵌套实现打印九九乘法表

思考&#xff1a; 外层循环主要用于控制循环的行数&#xff0c;内层循环用于控制列数。 基本语法&#xff1a; # 外层循环 for i in 序列1:# 内层循环for j in 序列2:循环体 序列1 序列2 &#xff0c;就可以是range(1, 10) -----也就是从1&#xff0c;到9。 参考while循环…...

mac安装并使用wireshark

mac安装并使用wireshark 1 介绍 我们在日常开发过程中&#xff0c;遇到了棘手的问题时&#xff0c;免不了查看具体网络请求情况&#xff0c;这个时候就需要用到抓包工具。比较著名的抓包工具就属&#xff1a;wireshark、fildder。我这里主要介绍wireshark。 2 安装 以mac安装为…...

torch张量的降维与升维

文章目录 一、降维和升维未完待续.... 一、降维和升维 squeeze和unsqueeze是torch张量常用的降维与升维的一种方式&#xff0c;但这种方式只能增添或减少大小为1的维度&#xff0c;如下&#xff1a; x1 torch.randn(1, 8, 256, 256) x1 torch.squeeze(x1,dim0) print(x1.sh…...

八大排序算法(C语言版)之插入排序

八大排序详解 目录&#xff1a;一、排序的概念1.1 排序的概念1.2 排序的应用 二、直接插入排序三、希尔排序四、排序算法复杂度及稳定性分析 目录&#xff1a; 八大排序算法&#xff1a; #mermaid-svg-7qCaGEYz0Jyj9dYw {font-family:"trebuchet ms",verdana,arial,…...

Linux系统安装redis并配置为服务

一、Linux环境 1、下载 官网提供的源码下载地址&#xff1a; https://github.com/redis/redis/archive/7.0.5.tar.gz 2、将源码上传至服务器 3、解压缩 # 将解压缩后的文件放置在同目录的source文件夹下 tar -zxvf redis-7.0.5.tar.gz -C ./source4、编译安装 对源码进行编…...

DDIO和DMA有什么区别

DDIO 和 DMA 的区别 DDIO (Data Direct I/O Technology) 主要应用: 主要用于网卡和CPU之间的数据传输。工作原理: 通过CPU的Last Level Cache (LLC) 直接与外部网卡交换数据&#xff0c;绕过了主存储器。优点: 减少了CPU和网卡等待内存的时间。提高了数据包的处理速度。减少了…...

【MATLAB源码-第58期】基于蛇优化算法(SO)和粒子群优化算法(PSO)的栅格地图路径规划最短路径和适应度曲线对比。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 粒子群算法 (Particle Swarm Optimization, PSO) 1. 算法概述 粒子群算法是一种基于群体智能的优化算法&#xff0c;模拟鸟群觅食的行为。算法中的每个粒子代表问题的一个可能解&#xff0c;并且具有位置和速度两个属性。粒…...

nlp与知识图谱代码解读

词嵌入 简单原理 我们要给一群14岁的孩子讲解词嵌入。可以使用一些比喻和生活中的例子&#xff1a; 老师&#xff1a; 你们还记得玩乐高积木的时候&#xff0c;每个积木块代表了一个特定的事物或形状吗&#xff1f;现在&#xff0c;想象一下&#xff0c;每个词都像是一个乐高…...

Redis设计与实现(3)字典

Redis的字典使用哈希表作为底层实现&#xff0c;一个哈希表里面可以有多个哈希表节点&#xff0c;而每一个哈希表节点就保存了字典中的一个键值对 redis字典所使用的哈希表由dict.h/dictht typedef struct dictht{//哈希表数组dictEntry **table;//哈希表大小unsigned long si…...

STM32MP157D BSP

一&#xff0c;全志R16、IMX6ULL和STM32MP157D启动相关 1&#xff0c;IMX6ULL是EMMC启动后&#xff0c;通过uboot fat命令的load进内存进行启动测试 2&#xff0c;openedv应该也是参考的官方的板子&#xff0c;类似调试口等均应该是一致的&#xff0c;所以目前就是用正点原子…...

最新SQL注入漏洞修复建议

点击星标&#xff0c;即时接收最新推文 本文选自《web安全攻防渗透测试实战指南&#xff08;第2版&#xff09;》 点击图片五折购书 SQL注入漏洞修复建议 常用的SQL注入漏洞的修复方法有两种。 1&#xff0e;过滤危险字符 多数CMS都采用过滤危险字符的方式&#xff0c;例如&…...

新人FPGA验证书籍推荐

1、FPGA之道 推荐理由&#xff1a;FPGA基础知识讲解全面&#xff0c;可以作为参考书时常翻阅&#xff1b; 2、Verilog数字系统设计教程 推荐理由&#xff1a;FPGA语法详细的介绍&#xff0c;案例比较有代表性&#xff1b; 工具类书籍推荐&#xff1a; 3、ModelSim电子系统…...

TypeError: data.reduce is not a function:数据类型不匹配

错误展示&#xff1a; 错误分析&#xff1a; 首先来看看前端代码&#xff1a;我表格绑定的数据模型是tableData&#xff0c;而我tableData定义的是一个数组 其次看看后端给的数据&#xff1a; 传递的是一个对象&#xff0c;而不是一个数组&#xff01; 这样原因就找出了&…...

出租屋智能视频监控系统方案:全面保卫租客安全

除了我们常见的家庭、社区、园区等智能监控&#xff0c;出租房作为很多人的暂住所也极易发生盗窃等事件&#xff0c;为保障大众租户的财产安全&#xff0c;旭帆科技特地针对出租屋制定了智能监控系统方案。 1、安装智能安防摄像头 高清晰度、夜视功能良好的智能摄像头&#xf…...

代码解读-自然语言处理

目录 demo3文本转为向量代码解读给出每一步的输出 demo3文本转为向量 代码 from tensorflow.keras.preprocessing.text import Tokenizer # 标记器(每一个词&#xff0c;以我们的数值做映射&#xff0c;)words [LaoWang has a Wechat account., He is not a nice person., …...

docker指令

镜像操作&#xff1a; # 搜索镜像 docker search image_name # 搜索结果过滤&#xff1a;是否是官方 docker search --filter --filter is-official image_name # 搜索结果过滤&#xff1a;是否是自动化构建 docker search --filter --filter is-automated image_name # 搜索结…...

【MySql】9- 实践篇(七)

文章目录 1. 一主多从的主备切换1.1 基于位点的主备切换1.2 GTID1.3 基于 GTID 的主备切换1.4 GTID 和在线 DDL 2. 读写分离问题2.1 强制走主库方案2.2 Sleep 方案2.3 判断主备无延迟方案2.4 配合 semi-sync方案2.5 等主库位点方案2.6 GTID 方案 3. 如何判断数据库是否出问题了…...

Maven compile时报错 系统资源不足,出现OOM:GC overhead limit exceeded

今天在对项目进行Maven clean compile的时候&#xff0c;报出了如下的错误&#xff0c; 系统资源不足。 有关详细信息&#xff0c;请参阅一下堆栈跟踪。 java.lang.OutOfMemoryError: GC overhead limit exceededat java.util.EnumSet.noneOf(EnumSet.java:115)at com.sun.too…...

启动内核ip转发和其他优化

1.临时修改 echo 1 > /proc/sys/net/ipv4/ip_forward echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse 2.配置文件修改 vim /etc/sysctl.conf net.ipv4.ip_forward 1 net.ipv4.tcp_tw_reuse 1 vm.swappiness 0 kernel.sysrq 1 net.ipv4.neigh.default.gc_stale_t…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

密码学基础——SM4算法

博客主页&#xff1a;christine-rr-CSDN博客 ​​​​专栏主页&#xff1a;密码学 &#x1f4cc; 【今日更新】&#x1f4cc; 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 ​编辑…...

flow_controllers

关键点&#xff1a; 流控制器类型&#xff1a; 同步&#xff08;Sync&#xff09;&#xff1a;发布操作会阻塞&#xff0c;直到数据被确认发送。异步&#xff08;Async&#xff09;&#xff1a;发布操作非阻塞&#xff0c;数据发送由后台线程处理。纯同步&#xff08;PureSync…...

对象回调初步研究

_OBJECT_TYPE结构分析 在介绍什么是对象回调前&#xff0c;首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例&#xff0c;用_OBJECT_TYPE这个结构来解析它&#xff0c;0x80处就是今天要介绍的回调链表&#xff0c;但是先不着急&#xff0c;先把目光…...