网络部分介绍

一部分是理论基础:OSI模型、TCP/IP协议、TCP、UDP、IP

另一部分编程基础:IO模型、BIO、NIO、AIO等Java网络IO模型

讲解网络 编程部分:

IO模型:阻塞IO、非阻塞IO、IO复用、信号驱动、异步IO

BIO模型

NIO模型

AIO模型

IO模型

Java IO读写原理

Java提供的IO操作:

操作字节:InputStream和OutputStream

操作字节:Reader和Writer

操作文件:File

操作网络:Socket

涉及网络IO编程的是BIO、NIO、AIO

用户程序进行IO的读写操作,基本都会用read和writer两大系统调用,不同系统名称可能不同功能大体是一样的

read系统调用:是把数据从内核换出去复制到用户空间进程缓冲区

writer系统调用:是把数据从用户进程缓冲区复制到内核缓冲区

两大系统调用都不负责内核缓冲区和磁盘/网卡之间的交换,底层读写交换,都由操作系统内核进行完成

内核缓冲区和用户进程缓冲区

缓冲区目的是为了减少频繁的系统IO调用,有了缓冲区,等待缓冲区到达一定数量的时候,再进行IO调用,提升性能,至于什么时候进行IO调用,由内核来决定,用户程序不用关心

Java中读写IO的底层流程

 典型的Java代码服务端处理过程:

1、客户端请求

硬件网卡,读取客户端请求的数据,将数据读取到内核缓冲区

2、获取请求数据

服务器从内核缓冲区读取数据到Java用户进程缓冲区

3、服务端业务处理

服务端在自己的用户空间中,处理客户端的请求

4、服务器返回数据

服务端将构建好的响应数据,从用户缓冲区写入内核缓冲区

5、发送到客户端

系统通过网络IO,将内核缓冲区数据,写入网卡,通过底层通信协议,将数据发送给目标客户端

同步/异步、阻塞/非阻塞

同步和异步:

同步和异步是基于应用程序与操作系统处理IO事件所采用的的方式;

同步方式处理IO事件,直接参与IO读写过程,必须阻塞在某个方法上面等待IO事件完成;

异步方式处理IO事件,所有的IO读写交给操作系统,应用程序只需要等待通知。如果没有通知,可以去做其他事件,并不需要完成真正IO操作,当操作完成会给应用程序一个通知

阻塞和非阻塞

阻塞和非阻塞是进程在访问数据的时候,数据是否准备就绪的一种处理方式。

阻塞:需要等待缓冲区数据准备好之后才能处理其他事情,否则会一直等待在哪里

非阻塞:进程访问数据缓冲区时,如果数据没有准备好则直接返回,如果数据准备好也直接返回

同步阻塞模式、同步非阻塞模式、异步阻塞模式、异步非阻塞模式

常见IO模型

Linux系统上提供的IO模型:

阻塞IO、非阻塞IO、IO复用、信号驱动IO、异步IO

以READ系统调用为例,获取到数据经历两个阶段:等待数据节点、将数据拷贝到用户空间

阻塞IO模型

阻塞IO从用户发起调用开始,数据等待、数据拷贝都是需要用户进程阻塞,直到数据拷贝完成返回,用户进程才可以继续执行,否则会一直阻塞

非阻塞IO模型

 非阻塞IO 中进程通过反复调用IO函数,判断数据是否准备好,采用轮询,占用CPU

IO复用

 主要使用复用器:select、poll、epoll

一个进程可以监听多个事件,能实现对多个IO 端口进行监听,多个连接共享一个等待机制

信号驱动IO模型

 首先需要开启套接字信号驱动功能,通过系统调用sigaction执行信号处理函数,信号处理函数直接返回,进程继续工作,当数据准备就绪好,生成一个sigio信号,通知应用程序取数据

异步IO

 信号驱动IO由内核通知进程可以开始一个IO操作,在用户进程进行IO操作时是需要等待的,所以是同步IO

异步IO模型由内核通知进程IO何时已经完成,进程不需要进行IO处理,所以是异步的

活动:周杰伦演唱会

角色1:举办方,售票业务员

角色2:黄牛

角色3:小明

角色4:送票快递员

阻塞IO:

小明从家先到演唱会现场售票业务员买票,但是票还没有出来,在现场等待一直等票出来然后买票回家

非阻塞IO:

小明从家里面先到演唱会现场问售票业务员买票,但是票还没出来,然后小明走了,办理其他事情去了,

然后过了2个小时,又去举办商售票大厅买票来了,如果票还没有出来,小明又先去办其他事情了

IO复用:

小明想买票看演唱会,都直接给黄牛(selector/epoll)打电话了,说帮我留意买个票,

票买了通知我,我自己去取(当我接到黄牛的电话时,我需要花费整个路程的时间去读这个数据,买拿这个票), 那么票没出来之前,小明完全可以做自己的事情

信号IO:

小明想买票看演唱会,给举办商售票业务员说,给给你留个电话,有票了请你给我打个电话通知一下

(是看人家操作系统提不提供这种功能,Linux提供,windows没有这种机制),我自己再来买票

(小明完全可以做自己的事情,但是票还是需要小明自己去拿的)

异步IO:

小明想买票看演唱会,给举办商售票业务员说(异步非阻塞i/o)打电话了,给你留个地址,有票了请通知快递员,把这张票送到这个地址来,当小明听到敲门声,看见快递员,就知道票好了,而且直到票好了的时候,票已经到他手上了,票不用小明自己去取(应用不用自己再去read数据了)

Socket网络编程

客户端和服务端:C/S模型 <-> B/S模型

Socket:套接字

Socket是一个抽象层,应用程序通过Socket进行发送和接收数据,可以向操作文件一样打开、读写和关闭操作。网络套接字是IP地址和端口组合

例如:IP地址为:127.0.0.1,端口是99,得到的套接字就是(“127.0.0.1”,99)

通信流程

 

编码:

/**
 * 服务端
 */
public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket = null;
        try {
            //创建ServerSocket实例接口客户端连接
            serverSocket = new ServerSocket();

            //绑定端口 6666
            serverSocket.bind(new InetSocketAddress(6666));
            System.out.println("服务端启动啦");

            //监听并接受客户端的连接
            Socket socket = serverSocket.accept();
            System.out.println("有新的客户端连接上");

            //进行读写操作 通过IO流进行操作
            InputStream inputStream = socket.getInputStream();

            byte[] bytes = new byte[100];
            //读取客户端发送数据
            int num = inputStream.read(bytes);
            System.out.println("客户端发送数据:"+new String(bytes,0,num));


            //关闭资源
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        try {
            //创建socket实例
            Socket socket = new Socket();
            System.out.println("客户端启动啦");

            //连接服务端,指定连接的服务端 IP和端口
            socket.connect(new InetSocketAddress("127.0.0.1",6666));
            System.out.println("连接服务端成功啦");

            //发送消息给服务端
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write("Hello Java".getBytes());
            System.out.println("发送给服务端消息完成");

            //关闭资源
            socket.close();

            System.out.println("客户端关闭");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

服务端流程

1.创建ServerSocket实例

2.绑定端口

3.监听并等待客户端的连接返回Socket实例

4.进行读写操作

5.关闭连接

客户端流程

1.创建Socket实例

2.通过IP+端口连接服务端

3.进行读写操作

4.关闭连接

通信过程方法

bind():指定本地地址

在创建ServerSocket实例之后,需要指定服务器的端口,建立一个本地连接,通过Socket进行通信

 

accept():接收连接请求

包含等待连接的状态,服务端通过ServerSocket实例来bind和listen创建一个套接字,服务端进入到accept状态,等待直到一个连接请求

connect():将套接字连接到目的地址

通过调用connect()为套接字绑定一个永久的目的地址,将客户端设置为连接状态,必须在进行流传输之前进行链接,否则无法传输数据

重要特点:

服务端先启动,然后再启动客户端

如果先启动客户端:ConnectException: Connection refused,原因在于服务端端口为绑定,客户端通过IP+端口无法找到服务端

主要类

ServerSocket类:

在Java.net包中有ServerSocket用于表示服务端套接字,其主要功能是等待来自网络上请求,通过指定的端口来等待连接套接字,服务端套接字一次可以与一个客户端连接(accept),如果有多个客户端的连接,连接过程会用到listen,将用户的额请求放入到客户的连接队列backlog,然后服务端从队列中获取客户端请求并建立连接。默认的队列大小是50,同一时刻多个连接请求如果超过最大的容量,则多出的连接会被拒绝。

构造函数都会抛出IOException异常,分为有以下类型:

ServerSocket():创建非绑定服务器套接字

ServerSocket(int port):创建绑定特定端口的服务器套接字

ServerSocket(int port, int backlog):利用backlog创建套接字并绑定端口号

ServerSocket(int port, int backlog, InetAddress bindAddr):使用指定端口,监听队列backlog和要绑定到本地的IP地址创建服务器,适用于计算机有多个网卡或者多个IP地址

InetSocketAddress类:

是与IP地址相关的类,利用该类可以设置或者获取IP地址以及主机信息

是SocketAddress的子类

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值