博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
网络编程- Socket-BIO
阅读量:2048 次
发布时间:2019-04-28

本文共 3929 字,大约阅读时间需要 13 分钟。

网络编程- Scoket-BIO

在这里插入图片描述

上图时对socket做一个简单介绍, 具体的实现这里就说了。主要将一下java网络编程几大IO模型实现、原理、演变,IO模型分别为BIOOS级别的NIO(NONBLOCKING IO)、NIO java jdk1.4升级的NEW IO

BIO模型

前提知识:想要彻底的了解IO模型及其原理和演变,你需要了解一下操作系统底层相关的一些系统调用知识,我上篇文章介绍过了,参考学习,有错误的望指出。

想必大家都知道IO操作肯定需要系统调用的,因为网络传输势必会用到网卡硬件,这就需要内核程序的参与,接下来详细介绍下整个BIO实现以及原理模型

大家先有个简单网络模型:

在这里插入图片描述

客户端和服务器端建立链接请求的时候肯定是调用了系统调用,那么系统调用又是怎么做的呢?

一下主要讲解服务器端
在这里插入图片描述
先抓包看下内核:
在这里插入图片描述
以上3和系统调用就是我们写建立连接的时候系统调用做的事。

在这里插入图片描述

系统调用通过这三个函数帮我们建立起服务器链接,并开启监听,监听客户端链接事件。并通过系统调用函数 accept() 方法接受客户端链接,因为一般需要链接多个客户端,所以需要用 while 无线循环去接受客户端。
在这里插入图片描述
但是accept方法是阻塞的,所以必须要等有至少一个客户端链接进来的时候才会继续下一步。(重点)
当有客户端链接进来的时候,服务器端需要对连接进行轮询去获取客户端发来的信息,通过 recv函数获取客户端数据。
在这里插入图片描述

以上是我们在服务器端建立链接,我们所需要的系统调用函数。

因为accpet 和 recv 都是阻塞函数,所以会产生一个问题:
如果客户端一直不发信息过来,系统会一直阻塞在那,遇到多个客户端链接时就会一直阻塞等待了,因为你的代码就一直阻塞在那了。
那么怎么解决呢,所以在我们java程序中我们会为每一个链接创建一个新的线程,去专门处理自己的链接发送的消息。
](https://img-blog.csdnimg.cn/20210530224635433.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMxMTQyMjM3,size_16,color_FFFFFF,t_70)

代码演示:

服务器端:

package com.socket;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;/** * 基于TCP协议 网络通讯编程(网络中客户端于服务器io流传输) * Created by Administrator on 2021/5/16. * Socket 服务器端 * 1. */public class SocketServerC {
public static void main(String[] args) throws IOException {
// 1. 创建server服务器,指定端口号,形成ip+端口构成唯一能识别的标识符套接字 ServerSocket serverSocket =new ServerSocket(5154); System.out.println("============等待连接============"); // 监听客户端连接,该方法线程阻塞,如果没有客户端连接,就阻塞一直等待。 // 优化:1.让服务器一直处理链接状态不要,链接到了就执行完关闭链接while循环 // 2. 因为下面很多地方线程阻塞,多个线程链接服务器时,产生效率问题,链接成功之后:使用多线程处理每一个链接 while(true) {
final Socket accept = serverSocket.accept(); // 阻塞, 系统调用accept函数 System.out.println("============成功连接了============" + accept.getInetAddress()); new Thread(new Runnable() {
public void run() {
try {
// 连接成功之后,读取客户端传来的网络IO对象,输入流 InputStream is = accept.getInputStream(); // 读取数据流,打印数据 // 定义一个缓存数组 byte[] bytes = new byte[1024]; int len = 0; // 系统调用 while (-1 != (len =is.read(bytes))){
// 阻塞--一直读取流通道,获取流数据,直到发现结束符才会跳出(File文件操作不会堵塞,因为读到最后会遇到EOF的) // 打印客户端发送过来的信息 System.out.println("客户端:" + new String(bytes, 0, len)); // 设置跳出条件,len长度小于bytes长度,这样就没办法持续读取流通道数据了,因为跳出了 if(len

客户端:

package com.socket;import java.io.BufferedOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.Socket;/** *  * 基于TCP协议 网络通讯编程(网络中客户端于服务器io流传输) *  Created by Administrator on 2021/5/16. *  Socket 客户端 */public class SocketClientC {
public static void SocketClientCC(Socket socket) throws IOException, InterruptedException {
// 通过ip+端口号 套接字 建立tcp链接 System.out.println("连接成功"); // 向服务器端发送信息 OutputStream os = socket.getOutputStream(); for (int i = 0; i < 10; i++) {
Thread.sleep(1000); os.write(("服务我来链接你了..."+i+"").getBytes()); } //获取服务器端发送过来的io输入流 InputStream is = socket.getInputStream(); byte[] bytes = new byte[1024]; int len = is.read(bytes); // 打印 System.out.println("服务器端:"+new String(bytes,0,len)); //socket.close(); } public static void main(String[] args) throws IOException, InterruptedException {
Socket socket = new Socket("127.0.0.1",5154); SocketClientCC(socket); }}

以上的实现方式就是传统的IO模式 即 BIO同步阻塞IO模型.

总结:

  1. BIO 每线程对应每一个链接
  2. 使用多线程可以接受很多了链接了

缺点:

如果线程数很大时,需要创建很多的线程去实现读写。

  1. 线程内存浪费。
  2. cpu调度消耗
    根本原因: accept 和 recv 阻塞(java中:accept 和 read 阻塞)

既然问题找到了,就肯定需要解决,既然链接多了需要很多线程不行,原因就是因为你阻塞了,那要是accept 和 read不阻塞了,那是不是就一个线程就行了。这样问题是不是就解决了。

上述的解决思想就是NIO ( NONBLOCKING IO ) 的实现思想,切记此处说的NIO 是站在操作系统层面的非阻塞同步IO模型(不是用多路复用器),而不是jdk提供的NEW NIO,此包用Selector对多路复用器的封装。下一篇讲解!

转载地址:http://rjhof.baihongyu.com/

你可能感兴趣的文章
Leetcode C++《每日一题》20200707 112. 路径总和
查看>>
Leetcode C++ 《第198场周赛-2》 1519. 子树中标签相同的节点数
查看>>
Leetcode C++ 《第199场周赛》
查看>>
Leetcode C++ 《第200场周赛》
查看>>
Leetcode C++ 《第201场周赛》
查看>>
云原生 第十章 应用存储和持久化数据卷:存储快照和拓扑调度
查看>>
云原生 第十一章 应用健康
查看>>
Leetcode C++ 《第202场周赛》
查看>>
云原生 第十二章 可观测性:监控与日志
查看>>
Leetcode C++ 《第203场周赛》
查看>>
云原生 第十三章 Kubernetes网络概念及策略控制
查看>>
《redis设计与实现》 第一部分:数据结构与对象 || 读书笔记
查看>>
《redis设计与实现》 第二部分(第9-11章):单机数据库的实现
查看>>
Leetcode C++《热题 Hot 100-70》23.合并K个升序链表
查看>>
6月13日-健身15
查看>>
6月17日-健身17
查看>>
6月20日-健身18
查看>>
有的人遇见就是一生
查看>>
冒险的勇气
查看>>
等待中邂逅命运
查看>>