Java网络编程面试题生命不止,折腾不休

2、tcp连接建立的时候3次握手,断开连接的4次握手的具体过程1

3、什么是同步?什么是异步?2

4、.什么是阻塞?什么是非阻塞?5

5、什么是阻塞IO?什么是非阻塞IO?6

6、什么是同步IO?什么是异步IO?7

7、IO模型有几种?分别是什么?8

8、Reactor和ProactorIO设计模式是什么?13

9、JavaNIO中的Buffer是什么?如何使用?16

10、Niobuffer的内部结构是什么?17

11、JavaNIO中的Channel是什么?有什么特点?18

12、JavaNIO中的Selector是什么?21

13、简单讲一下文件IO中的Path和Files22

14、select、poll和epoll的区别23

15、网络编程中设计并发服务器,使用多进程与多线程,请问有什么区别?29

15、网络编程的一般步骤29

16、TCP的全称是31

17、UDP的全称是31

18、请说出TCP和UDP的区别31

19、TCP为什么不是两次连接?而是三次握手?33

20、说明socket是什么?34

21、为什么需要端口端口是真实存在的还是虚拟的概念35

22、Java中,端口使用两个字节表示,可以表示多少个端口UDP和TCP端口是各自独立的吗35

23、URL类有什么作用35

24、基于TCP的Socket网络编程的主要步骤是什么?36

25、【上机】写出建立TCP服务器ServerSocket的代码。并说明accept方法有什么特点37

26、【上机】写出建立TCP客户端Socket的代码。并说明建立Socket后,通过什么方法Socket获得流对象37

27、基于UDP的Socket网络编程的主要步骤是什么?37

28、【上机】使用UDP的方式,完成对象的传递。38

30、NIO和传统BIO区别是什么?40

31、JavaNIO的几个核心组成部分是什么?作用分别是什么?41

35、HTTP协议中常用的请求方法有哪些50

36、常见的HTTP状态码有哪些51

37、HTTP协议中content-type指的是什么?55

38、网络传输协议本质和作用是什么?65

39、可以实现一个简单的网络协议吗?65

TCP:是面向连接的流传输控制协议,具有高可靠性,确保传输数据的正确性,有验证重发机制,因此不会出现丢失或乱序。

UDP:是无连接的数据报服务,不对数据报进行检查与修改,无须等待对方的应答,会出现分组丢失、重复、乱序,但具有较好的实时性,UDP段结构比TCP的段结构简单,因此网络开销也小。

l第一次握手是客户端connect连接到server

l第二次serveracceptclient的请求之后,向client端发送一个消息,相当于说我都准备好了,你连接上我了

l第三次就是client向server发送的,就是对第二次握手消息的确认。之后client和server就开始通讯了。

2.断开连接的4次握手,具体如下:

l断开连接的一端发送close请求是第一次握手

l另外一端接收到断开连接的请求之后需要对close进行确认,发送一个消息,这是第二次握手

l发送了确认消息之后还要向对端发送close消息,要关闭对对端的连接,这是第3次握手

l而在最初发送断开连接的一端接收到消息之后,进入到一个很重要的状态time_wait状态,这个状态也是面试官经常问道的问题,最后一次握手是最初发送断开连接的一端接收到消息之后。对消息的确认。

同步:

如果有多个任务或者事件要发生,这些任务或者事件必须逐个地进行,一个事件或者任务的执行会导致整个流程的暂时等待,这些事件没有办法并发地执行;

异步:

如果有多个任务或者事件发生,这些事件可以并发地执行,一个事件或者任务的执行不会导致整个流程的暂时等待。

这就是同步和异步。

举个简单的例子,假如有一个任务包括两个子任务A和B,对于同步来说,当A在执行的过程中,B只有等待,直至A执行完毕,B才能执行;而对于异步就是A和B可以并发地执行,B不必等待A执行完毕之后再执行,这样就不会由于A的执行导致整个任务的暂时等待。

如果还不理解,可以先看下面这2段代码:

voidfun1(){

}

voidfun2(){

voidfunction(){

fun1();

fun2()

.....

这段代码就是典型的同步,在方法function中,fun1在执行的过程中会导致后续的fun2无法执行,fun2必须等待fun1执行完毕才可以执行。

接着看下面这段代码:

newThread(){

publicvoidrun(){

}.start();

fun2();

这段代码是一种典型的异步,fun1的执行不会影响到fun2的执行,并且fun1和fun2的执行不会导致其后续的执行过程处于暂时的等待。

事实上,同步和异步是一个非常广的概念,它们的重点在于多个任务和事件发生时,一个事件的发生或执行是否会导致整个流程的暂时等待。我觉得可以将同步和异步与Java中的synchronized关键字联系起来进行类比。当多个线程同时访问一个变量时,每个线程访问该变量就是一个事件,对于同步来说,就是这些线程必须逐个地来访问该变量,一个线程在访问该变量的过程中,其他线程必须等待;而对于异步来说,就是多个线程不必逐个地访问该变量,可以同时进行访问。

同步和异步可以表现在很多方面,但是记住其关键在于多个任务和事件发生时,一个事件的发生或执行是否会导致整个流程的暂时等待。一般来说,可以通过多线程的方式来实现异步,但是千万记住不要将多线程和异步画上等号,异步只是宏观上的一个模式,采用多线程来实现异步只是一种手段,并且通过多进程的方式也可以实现异步。同步和异步着重点在于多个任务的执行过程中,一个任务的执行是否会导致整个流程的暂时等待

阻塞:

当某个事件或者任务在执行过程中,它发出一个请求操作,但是由于该请求操作需要的条件不满足,那么就会一直在那等待,直至条件满足;

非阻塞:

当某个事件或者任务在执行过程中,它发出一个请求操作,如果该请求操作需要的条件不满足,会立即返回一个标志信息告知条件不满足,不会一直在那等待。

举个简单的例子:

假如我要读取一个文件中的内容,如果此时文件中没有内容可读,对于同步来说就是会一直在那等待,直至文件中有内容可读;而对于非阻塞来说,就会直接返回一个标志信息告知文件中暂时无内容可读。

阻塞和非阻塞着重点在于发出一个请求操作时,如果进行操作的条件不满足是否会返会一个标志信息告知条件不满足。理解阻塞和非阻塞可以同线程阻塞类比地理解,当一个线程进行一个请求操作时,如果条件不满足,则会被阻塞,即在那等待条件满足。

在了解阻塞IO和非阻塞IO之前,先看下一个具体的IO操作过程是怎么进行的。

通常来说,IO操作包括:对硬盘的读写、对socket的读写以及外设的读写。

当用户线程发起一个IO请求操作(本文以读请求操作为例),内核会去查看要读取的数据是否就绪,对于阻塞IO来说,如果数据没有就绪,则会一直在那等待,直到数据就绪;对于非阻塞IO来说,如果数据没有就绪,则会返回一个标志信息告知用户线程当前要读的数据没有就绪。当数据就绪之后,便将数据拷贝到用户线程,这样才完成了一个完整的IO读请求操作,也就是说一个完整的IO读请求操作包括两个阶段:

1)查看数据是否就绪;

2)进行数据拷贝(内核将数据拷贝到用户线程)。

那么阻塞(blockingIO)和非阻塞(non-blockingIO)的区别就在于第一个阶段,如果数据没有就绪,在查看数据是否就绪的过程中是一直等待,还是直接返回一个标志信息。

Java中传统的IO都是阻塞IO,比如通过socket来读数据,调用read()方法之后,如果数据没有就绪,当前线程就会一直阻塞在read方法调用那里,直到有数据才返回;

而如果是非阻塞IO的话,当数据没有就绪,read()方法应该返回一个标志信息,告知当前线程数据没有就绪,而不是一直在那里等待。

我们先来看一下同步IO和异步IO的定义,在《Unix网络编程》一书中对同步IO和异步IO的定义是这样的:

AsynchronousI/OoperationcausestherequestingprocesstobeblockeduntilthatI/Ooperationcompletes.

AnasynchronousI/Ooperationdoesnotcausetherequestingprocesstobeblocked.

从字面的意思可以看出:同步IO即如果一个线程请求进行IO操作,在IO操作完成之前,该线程会被阻塞;而异步IO为如果一个线程请求进行IO操作,IO操作不会导致请求线程被阻塞。

事实上,同步IO和异步IO模型是针对用户线程和内核的交互来说的:

对于同步IO:当用户发出IO请求操作之后,如果数据没有就绪,需要通过用户线程或者内核不断地去轮询数据是否就绪,当数据就绪时,再将数据从内核拷贝到用户线程;

而异步IO:只有IO请求操作的发出是由用户线程来进行的,IO操作的两个阶段都是由内核自动完成,然后发送通知告知用户线程IO操作已经完成。也就是说在异步IO中,不会对用户线程产生任何阻塞。

这是同步IO和异步IO关键区别所在,同步IO和异步IO的关键区别反映在数据拷贝阶段是由用户线程完成还是内核完成。所以说异步IO必须要有操作系统的底层支持。

注意同步IO和异步IO与阻塞IO和非阻塞IO是不同的两组概念。

阻塞IO和非阻塞IO是反映在当用户请求IO操作时,如果数据没有就绪,是用户线程一直等待数据就绪,还是会收到一个标志信息这一点上面的。也就是说,阻塞IO和非阻塞IO是反映在IO操作的第一个阶段,在查看数据是否就绪时是如何处理的。

在《Unix网络编程》一书中提到了五种IO模型

分别是:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。

下面就分别来介绍一下这5种IO模型的异同。

1.阻塞IO模型

最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。

当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。

典型的阻塞IO模型的例子为:

data=socket.read();

如果数据没有就绪,就会一直阻塞在read方法。

2.非阻塞IO模型

当用户线程发起一个read操作后,并不需要等待,而是马上就得到了一个结果。如果结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。

所以事实上,在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU。

典型的非阻塞IO模型一般如下:

伪代码

while(true){

newMyThread(socket)

classMyThread{

if(data!=error){

处理数据

break;

但是对于非阻塞IO就有一个非常严重的问题,在while循环中需要不断地去询问内核数据是否就绪,这样会导致CPU占用率非常高,因此一般情况下很少使用while循环这种方式来读取数据。

3.多路复用IO模型

多路复用IO模型是目前使用得比较多的模型。JavaNIO实际上就是多路复用IO。

在多路复用IO模型中,会有一个线程不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket读写事件进行时,才会使用IO资源,所以它大大减少了资源占用。

在JavaNIO中,是通过selector.select()去查询每个通道是否有到达事件,如果没有事件,则一直阻塞在那里,因此这种方式会导致用户线程的阻塞。

也许有朋友会说,我可以采用多线程+阻塞IO达到类似的效果,但是由于在多线程+阻塞IO中,每个socket对应一个线程,这样会造成很大的资源占用,并且尤其是对于长连接来说,线程的资源一直不会释放,如果后面陆续有很多连接的话,就会造成性能上的瓶颈。

而多路复用IO模式,通过一个线程就可以管理多个socket,只有当socket真正有读写事件发生才会占用资源来进行实际的读写操作。因此,多路复用IO比较适合连接数比较多的情况。

另外多路复用IO为何比非阻塞IO模型的效率高是因为在非阻塞IO中,不断地询问socket状态时通过用户线程去进行的,而在多路复用IO中,轮询每个socket状态是内核在进行的,这个效率要比用户线程要高的多。

不过要注意的是,多路复用IO模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于多路复用IO模型来说,一旦事件响应体很大,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询。

4.信号驱动IO模型

在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用IO读写操作来进行实际的IO请求操作。

5.异步IO模型

异步IO模型才是最理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。

而另一方面,从内核的角度,当它受到一个asynchronousread之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。

然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。

也就说用户线程完全不需要实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。

也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。

用户线程中不需要再次调用IO函数进行具体的读写。

这点是和信号驱动模型有所不同的

在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用iO函数进行实际的读写操作。

注意,异步IO是需要操作系统的底层支持,在Java7中,提供了AsynchronousIO。也就是java中的AIO

前面四种IO模型实际上都属于同步IO,只有最后一种是真正的异步IO,因为无论是多路复用IO还是信号驱动模型,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。

在传统的网络服务设计模式中,有两种比较经典的模式:一种是多线程,一种是线程池。

对于多线程模式,也就说来了client,服务器就会新建一个线程来处理该client的读写事件,如下图所示:

这种模式虽然处理起来简单方便,但是由于服务器为每个client的连接都采用一个线程去处理,使得资源占用非常大。因此,当连接数量达到上限时,再有用户请求连接,直接会导致资源瓶颈,严重的可能会直接导致服务器崩溃。

因此,为了解决这种一个线程对应一个客户端模式带来的问题,提出了采用线程池的方式,也就说创建一个固定大小的线程池,来一个客户端,就从线程池取一个空闲线程来处理,当客户端处理完读写操作之后,就交出对线程的占用。因此这样就避免为每一个客户端都要创建线程带来的资源浪费,使得线程可以重用。

因此便出现了下面的两种高性能IO设计模式:Reactor和Proactor。

在Reactor模式中,会先对每个client注册感兴趣的事件,然后有一个线程专门去轮询每个client是否有事件发生,当有事件发生时,便顺序处理每个事件,当所有事件处理完之后,便再转去继续轮询,如下图所示:

多路复用IO就是采用Reactor模式。注意,上面的图中展示的是顺序处理每个事件,当然为了提高事件处理速度,可以通过多线程或者线程池的方式来处理事件。

在Proactor模式中,当检测到有事件发生时,会新起一个异步操作,然后交由内核线程去处理,当内核线程完成IO操作之后,发送一个通知告知操作已完成,可以得知,异步IO模型采用的就是Proactor模式。

Buffer(缓冲区):

JavaNIOBuffers用于和NIOChannel交互。我们从Channel中读取数据到buffers里,从Buffer把数据写入到Channels;

Buffer本质上就是一块内存区;

一个Buffer有三个属性是必须掌握的,分别是:capacity容量、position位置、limit限制。

Buffer的常见方法

Bufferclear()

Bufferflip()

Bufferrewind()

Bufferposition(intnewPosition)

Buffer的使用方式/方法介绍:

分配缓冲区(AllocatingaBuffer):

ByteBufferbuf=ByteBuffer.allocate(28);//以ByteBuffer为例子

写入数据到缓冲区(WritingDatatoaBuffer)

写数据到Buffer有两种方法:

1.从Channel中写数据到Buffer

intbytesRead=inChannel.read(buf);//readintobuffer.

2.通过put写数据:

buf.put(127);

一个buffer主要由position,limit,capacity三个变量来控制读写的过程。此三个变量的含义见如下表格:

参数

写模式

读模式

position

当前写入的单位数据数量。

当前读取的单位数据位置。

limit

代表最多能写多少单位数据和容量是一样的。

代表最多能读多少单位数据,和之前写入的单位数据量一致。

capacity

buffer容量

Buffer常见方法:

flip():写模式转换成读模式

rewind():将position重置为0,一般用于重复读。

clear():清空buffer,准备再次被写入(position变成0,limit变成capacity)。

compact():将未读取的数据拷贝到buffer的头部位。

mark()、reset():mark可以标记一个位置,reset可以重置到该位置。

Buffer常见类型:ByteBuffer、MappedByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer。

channel常见类型:FileChannel、DatagramChannel(UDP)、SocketChannel(TCP)、ServerSocketChannel(TCP)

Channel:

JavaNIO中的SocketChannel是一个连接到TCP网络套接字的通道。

可以通过以下2种方式创建SocketChannel:

打开SocketChannel下面是SocketChannel的打开方式:

SocketChannelsocketChannel=SocketChannel.open();

关闭SocketChannel

当用完SocketChannel之后调用SocketChannel.close()关闭SocketChannel:socketChannel.close();

从SocketChannel读取数据

要从SocketChannel中读取数据,调用一个read()的方法之一。

ByteBufferbuf=ByteBuffer.allocate(48);

intbytesRead=socketChannel.read(buf);

非阻塞模式

可以设置SocketChannel为非阻塞模式(non-blockingmode).设置之后,就可以在异步模式下调用connect(),read()和write()了。

如果SocketChannel在非阻塞模式下,此时调用connect(),该方法可能在连接建立之前就返回了。为了确定连接是否建立,可以调用finishConnect()的方法。

像这样:

socketChannel.configureBlocking(false);

while(!socketChannel.finishConnect()){

//wait,ordosomethingelse...

JavaNIOChannel通道和流非常相似,主要有以下几点区别:

l通道可以读也可以写,流一般来说是单向的(只能读或者写,所以之前我们用流进行IO操作的时候需要分别创建一个输入流和一个输出流)。

l通道可以异步读写。

l通道总是基于缓冲区Buffer来读写。

JavaNIO中最重要的几个Channel的实现:

lFileChannel:用于文件的数据读写

lDatagramChannel:用于UDP的数据读写

lSocketChannel:用于TCP的数据读写,一般是客户端实现

lServerSocketChannel:允许我们监听TCP链接请求,每个请求会创建会一个SocketChannel,一般是服务器实现

类层次结构

Selector(选择器):

Selector一般称为选择器,当然你也可以翻译为多路复用器。

它是JavaNIO核心组件中的一个,用于检查一个或多个NIOChannel(通道)的状态是否处于可读、可写。

如此可以实现单线程管理多个channels,也就是可以管理多个网络链接。

使用Selector的好处在于:使用更少的线程来就可以来处理通道了,相比使用多个线程,避免了线程上下文切换带来的开销。

Selector(选择器)的使用方法介绍

Selector的创建

Selectorselector=Selector.open();

注册Channel到Selector(Channel必须是非阻塞的)

channel.configureBlocking(false);

SelectionKeykey=channel.register(selector,Selectionkey.OP_READ);

SelectionKey介绍

一个SelectionKey键表示了一个特定的通道对象和一个特定的选择器对象之间的注册关系。

从Selector中选择channel(SelectingChannelsviaaSelector)

选择器维护注册过的通道的集合,并且这种注册关系都被封装在SelectionKey当中.

停止选择的方法

wakeup()方法和close()方法。

文件I/O基石:Path:

创建一个Path

File和Path之间的转换,File和URI之间的转换

移除Path中的冗余项

Files类:

Files.exists()检测文件路径是否存在

Files.createFile()创建文件

Files.createDirectories()和Files.createDirectory()创建文件夹

Files.delete()方法可以删除一个文件或目录

Files.copy()方法可以吧一个文件从一个地址复制到另一个位置

获取文件属性

遍历一个文件夹

Files.walkFileTree()遍历整个目录

在linux没有实现epoll事件驱动机制之前,我们一般选择用select或者poll等IO多路复用的方法来实现并发服务程序。在大数据、高并发、集群等一些名词唱得火热之年代,select和poll的用武之地越来越有限,风头已经被epoll占尽。

select的缺点:

在linux内核头文件中,有这样的定义:

#define__FD_SETSIZE1024

相比select模型,poll使用链表保存文件描述符,因此没有了监视文件数量的限制,但其他三个缺点依然存在。

拿select模型为例,假设我们的服务器需要支持100万的并发连接,则在__FD_SETSIZE为1024的情况下,则我们至少需要开辟1k个进程才能实现100万的并发连接。

因此,基于select模型的服务器程序,要达到10万级别的并发访问,是一个很难完成的任务。

epoll的实现机制与select/poll机制完全不同,上面所说的select的缺点在epoll上不复存在。

设想一下如下场景:

有100万个客户端同时与一个服务器进程保持着TCP连接。而每一时刻,通常只有几百上千个TCP连接是活跃的(事实上大部分场景都是这种情况)。如何实现这样的高并发?

在select/poll时代,服务器进程每次都把这100万个连接告诉操作系统(从用户态复制句柄数据结构到内核态),让操作系统内核去查询这些套接字上是否有事件发生,轮询完后,再将句柄数据复制到用户态,让服务器应用程序轮询处理已发生的网络事件,这一过程资源消耗较大,因此,select/poll一般只能处理几千的并发连接。

epoll的设计和实现与select完全不同。

epoll通过在Linux内核中申请一个简易的文件系统

(文件系统一般用什么数据结构实现?B+树)

把原先的select/poll调用分成了3个部分:

1)调用epoll_create()建立一个epoll对象(在epoll文件系统中为这个句柄对象分配资源)

2)调用epoll_ctl向epoll对象中添加这100万个连接的套接字

3)调用epoll_wait收集发生的事件的连接

如此一来,要实现上面说是的场景,只需要在进程启动时建立一个epoll对象,然后在需要的时候向这个epoll对象中添加或者删除连接。同时,epoll_wait的效率也非常高,因为调用epoll_wait时,并没有一股脑的向操作系统复制这100万个连接的句柄数据,内核也不需要去遍历全部的连接。

下面来看看Linux内核具体的epoll机制实现思路。

structeventpoll{

....

/*红黑树的根节点,这颗树中存储着所有添加到epoll中的需要监控的事件*/

structrb_rootrbr;

/*双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件*/

structlist_headrdlist;

};

而所有添加到epoll中的事件都会与设备(网卡)驱动程序建立回调关系,也就是说,当相应的事件发生时会调用这个回调方法。这个回调方法在内核中叫ep_poll_callback,它会将发生的事件添加到rdlist双链表中。

在epoll中,对于每一个事件,都会建立一个epitem结构体,如下所示:

structepitem{

structrb_noderbn;//红黑树节点

structlist_headrdllink;//双向链表节点

structepoll_filefdffd;//事件句柄信息

structeventpoll*ep;//指向其所属的eventpoll对象

structepoll_eventevent;//期待发生的事件类型

当调用epoll_wait检查是否有事件发生时,只需要检查eventpoll对象中的rdlist双链表中是否有epitem元素即可。如果rdlist不为空,则把发生的事件复制到用户态,同时将事件数量返回给用户。

通过红黑树和双链表数据结构,并结合操作系统底层回调机制,造就了epoll的高效

epoll的用法

第一步:epoll_create()系统调用。此调用返回一个句柄,之后所有的使用都依靠这个句柄来标识。

第二步:epoll_ctl()系统调用。通过此调用向epoll对象中添加、删除、修改感兴趣的事件,返回0标识成功,返回-1表示失败。

第三部:epoll_wait()系统调用。通过此调用收集收集在epoll监控中已经发生的事件。

15、网络编程中设计并发服务器,使用多进程与多线程,请问有什么区别?1,进程:

子进程是父进程的复制品。

子进程获得父进程数据空间、堆和栈的复制品。2,线程:

相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。

线程执行开销小,但不利于资源管理和保护;而进程正相反。

同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。

SMP的全称是"对称多处理"(SymmetricalMulti-Processing)技术,是指在一个计算机上汇集了一组处理器(多CPU),各CPU之间共享内存子系统以及总线结构。

对于TCP连接:

1.服务器端

1)创建套接字create;

2)绑定端口号bind;

3)监听连接listen;

4)接受连接请求accept,并返回新的套接字;

5)用新返回的套接字recv/send;

6)关闭套接字。

2.客户端

1)创建套接字create;

2)发起建立连接请求connect;

3)发送/接收数据send/recv;

4)关闭套接字。

TCP总结:

Server端:create–bind–listen–accept–recv/send–close

Client端:create——-conncet——send/recv——close.

对于UDP连接:

1.服务器端:

3)接收/发送消息recvfrom/sendto;

2.客户端:

2)发送/接收消息sendto/recvfrom;

3)关闭套接字.

UDP总结:

Server端:create—-bind—-recvfrom/sendto—-close

Client端:create—-sendto/recvfrom—-close.

函数原型intrecv(_In_SOCKETs,_Out_char*buf,_In_intlen,_In_intflags);

TransferControlProtocol。

UserDatagramProtocol。

TCP:

一种面向连接(连接导向)的、可靠的、基于字节流的传输层(Transportlayer)通信协议。

特点:

面向连接;

点到点的通信;

高可靠性;

占用系统资源多、效率低;

UDP:

一种无连接的、提供面向事务的简单不可靠信息传送服务的传输层通信协议。

特点:

非面向连接

传输不可靠,可能丢失

发送不管对方是否准备好,接收方收到也不确认

可以广播发送

非常简单的协议,开销小

TCP—传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

UDP—用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快

如果A与B两个进程通信,如果仅是两次连接。

可能出现的一种情况

B收到报文后,会向A发起连接。此时两次握手完毕

B会认为已经建立了连接可以通信,B会一直等到A发送的连接请求

而A对失效的报文回复自然不会处理。

因此会陷入B忙等的僵局,造成资源的浪费。

从上图可以看到:底层的东西已经被内核实现了,即我们通常意义上的内核协议栈(传输层,网络层,链路层)

最上面的Application(应用层)是我们用户所要实现的,它是属于用户进程的一部分,工作在用户空间,那么用户空间的程序要想访问内核,使用内核的服务,就需要一个接口,去访问所需要的服务

对于网络编程来说,这个接口就是套接口(Socket)。

Socket:可以看作用户进程和内核网络协议栈编程(交互)接口

Socket:不仅可以在同一台主机上进行通信,也可以在网络上不同的主机间进行通信,也可以异构(软硬件平台不同)进行通信(手机qq和PC机上的qq进行通信,手机的系统是ARM,而PC机是x86)

IP地址用来标志一台计算机,但是一台计算机上可能提供多种网络应用程序,使用端口来区分这些应用程序。

端口是虚拟的概念,并不是说在主机上真的有若干个端口。通过端口,可以在一个主机上运行多个网络应用程序。

端口范围0---65535,16位整数。

由于TCP/IP传输层的两个协议TCP和UDP是完全独立的两个软件模块,因此各自的端口号也相互独立,如TCP有一个255号端口,UDP也可以有一个255号端口,二者并不冲突。

URL:UniformResourceLocator,统一资源定位器;俗称“网址”,如:

由4部分组成:

l存放资源的主机域名:www.baidu.com;

l端口号:80;

l资源文件名:index.html#aacansu=bjsxt;

URL是指向互联网“资源”的指针。资源可以是简单的文件或目录,也可以是对更为复杂的对象的引用,例如对数据库或搜索引擎的查询。

基于TCP协议的Socket编程的主要步骤

服务器端(server):

1.构建一个ServerSocket实例,指定本地的端口。这个socket就是用来监听指定端口的连接请求的。

2.重复如下几个步骤:

a.调用socket的accept()方法来获得下面客户端的连接请求。通过accept()方法返回的socket实例,建立了一个和客户端的新连接。

b.通过这个返回的socket实例获取InputStream和OutputStream,可以通过这两个stream来分别读和写数据。

c.结束的时候调用socket实例的close()方法关闭socket连接。

客户端(client):

1.构建Socket实例,通过指定的远程服务器地址和端口来建立连接。

2.通过Socket实例包含的InputStream和OutputStream来进行数据的读写。

3.操作结束后调用socket实例的close方法,关闭。

//服务器监听请求;

ServerSocketss=newServerSocket(9999);

//接受请求:创建了socket;

Socketsocket=ss.accept();

详见课上示例。

//客户端向服务器端发送请求;

Socketsocket=newSocket("127.0.0.1",9999);

//建好连接后,开始传输数据;

OutputStreamos=socket.getOutputStream();

基于UDP协议的Socket编程的主要步骤

1.构造DatagramSocket实例,指定本地端口。

2.通过DatagramSocket实例的receive方法接收DatagramPacket.DatagramPacket中间就包含了通信的内容。

3.通过DatagramSocket的send和receive方法来收和发DatagramPacket.

1.构造DatagramSocket实例。

2.通过DatagramSocket实例的send和receive方法发送DatagramPacket报文。

3.结束后,调用DatagramSocket的close方法关闭。

(1)客户端向服务器端传送对象信息;

DatagramSocketds=newDatagramSocket(9999);

//构建数据包;

Scannerinput=newScanner(System.in);

System.out.println("请输入用户名:");

Stringusername=input.nextLine();

System.out.println("请输入密码:");

Stringpassword=input.nextLine();

//事先要创建好User类;

Useruser=newUser(username,password);

//字节流;在内存开辟缓冲区;

ByteArrayOutputStreambaos=newByteArrayOutputStream();

ObjectOutputStreamoos=newObjectOutputStream(baos);

oos.writeObject(user);

bytebuf[]=baos.toByteArray();

DatagramPacketdp=newDatagramPacket(buf,buf.length,InetAddress.getByName("127.0.0.1"),8888);//DatagramPacket只用byte[]数组;

//发送数据;

ds.send(dp);

(2)服务器端从客户端接收对象信息;

//服务器定义DatagramSocket以接收数据;

DatagramSocketds=newDatagramSocket(8888);

//定义一个数据包来接收数据;

//数据包里是byte数组,所以还得定义一个byte数组;

bytebuf[]=newbyte[1024];

DatagramPacketdp=newDatagramPacket(buf,buf.length);

//接收客户端发过来的数据;

ds.receive(dp);

//用字节流和对象流读取对象信息;

ByteArrayInputStreambais=newByteArrayInputStream(buf);

ObjectInputStreamois=newObjectInputStream(bais);

Useruser=(User)ois.readObject();

System.out.println(user);

NIOvsBIO之间的理念上面的区别(NIO将阻塞交给了后台线程执行)

IO是面向流的,NIO是面向缓冲区的

JavaBIO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方;

NIO则能前后移动流中的数据,因为是面向缓冲区的BIO流是阻塞的,NIO流是不阻塞的JavaIO的各种流是阻塞的。

这意味着,当一个线程调用read()或write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。

该线程在此期间不能再干任何事情了JavaNIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。

NIO可让您只使用一个(或几个)单线程管理多个通道(网络连接或文件),但付出的代价是解析数据可能会比从一个阻塞流中读取数据更复杂。

非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。

选择器

JavaNIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器,然后使用一个单独的线程来“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道。

lChannels

lBuffers

lSelectors

基本上,所有的IO在NIO中都从一个Channel开始。

Channel有点象流。

数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中。

Channel的实现:

(涵盖了UDP和TCP网络IO,以及文件IO)

lFileChannel

lDatagramChannel

lSocketChannel

lServerSocketChannel

读数据:

intbytesRead=inChannel.read(buf);

写数据:

intbytesWritten=inChannel.write(buf);

Buffer

Buffer实现:(byte,char、short,int,long,float,double)

lByteBuffer

lCharBuffer

lDoubleBuffer

lFloatBuffer

lIntBuffer

lLongBuffer

lShortBuffer

Buffer使用

l读数据flip()方法:

buf.flip();

将Buffer从写模式切换到读模式调用flip()方法会将position设回0,并将limit设置成之前position的值。

l(char)buf.get()

读取数据

lBuffer.rewind()

将position设回0,所以你可以重读Buffer中的所有数据limit保持不变,仍然表示能从Buffer中读取多少个元素(byte、char等)

lBuffer.mark()方法,

可以标记Buffer中的一个特定position。

之后可以通过调用Buffer.reset()方法,恢复到Buffer.mark()标记时的position

一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。

lclear()方法:

清空整个缓冲区。position将被设回0,limit被设置成capacity的值

lcompact()方法:

只会清除已经读过的数据;任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。

将position设到最后一个未读元素正后面,limit被设置成capacity的值写数据buf.put(127);

Buffer的三个属性

capacity:

l表示容量

lBuffer的一个固定的大小值;

lBuffer满了需要将其清空才能再写;

lByteBuffer.allocate(48);该buffer的capacity为48byteCharBuffer.allocate(1024);该buffer的capacity为1024个char

position:

含义取决于Buffer处在读模式还是写模式(初始值为0,写或者读操作的当前位置)

写数据时,初始的position值为0;

其值最大可为capacity-1

将Buffer从写模式切换到读模式,position会被重置为0

limit:

含义取决于Buffer处在读模式还是写模式(写limit=capacity;读limit等于最多可以读取到的数据)

写模式下,limit等于Buffer的capacity切换Buffer到读模式时,limit表示你最多能读到多少数据;

Selector

Selector允许单线程处理多个Channel。

如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便。

例如,在一个聊天服务器中。

要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。

一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接收等。

使用

创建:

Selectorselector=Selector.open();注册通道:channel.configureBlocking(false);//与Selector一起使用时,Channel必须处于非阻塞模式

//这意味着不能将FileChannel与Selector一起使用,因为FileChannel不能切换到非阻塞模式(而套接字通道都可以)

SelectionKeykey=channel.register(selector,Selectionkey.OP_READ);//第二个参数表明Selector监听Channel时对什么事件感兴趣

//SelectionKey.OP_CONNECTSelectionKey.OP_ACCEPTSelectionKey.OP_READSelectionKey.OP_WRITE//可以用或操作符将多个兴趣组合一起

SelectionKey包含了interest集合、ready集合、Channel、Selector、附加的对象(可选)

intinterestSet=key.interestOps();

可以进行类似interestSet&SelectionKey.OP_CONNECT的判断

select():

阻塞到至少有一个通道在你注册的事件上就绪了

selectNow():

不会阻塞,不管什么通道就绪都立刻返回

selectedKeys():

访问“已选择键集(selectedkeyset)”中的就绪通道

close():

使用完selector需要用其close()方法会关闭该Selector,且使注册到该Selector上的所有SelectionKey实例无效

SetselectedKeys=selector.selectedKeys();

IteratorkeyIterator=selectedKeys.iterator();

while(keyIterator.hasNext()){

SelectionKeykey=keyIterator.next();

if(key.isAcceptable()){

//aconnectionwasacceptedbyaServerSocketChannel.

}elseif(key.isConnectable()){

//aconnectionwasestablishedwitharemoteserver.

}elseif(key.isReadable()){

//achannelisreadyforreading

}elseif(key.isWritable()){

//achannelisreadyforwriting

keyIterator.remove();//注意这里必须手动remove;

表明该selectkey我已经处理过了;

HTTP协议是HyperTextTransferProtocol(超文本传输协议)的缩写,是用于从万维网(WWW:WorldWideWeb)服务器传输超文本到本地浏览器的传送协议。

HTTP是一个基于TCP/IP通信协议来传递数据(HTML文件,图片文件,查询结果等)。

HTTP工作原理

HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。

Web服务器有:Apache服务器,Nginx,IIS服务器(InternetInformationServices)等。

Web服务器根据接收到的请求后,向客户端发送响应信息。

HTTP默认端口号为80,但是你也可以改为8080或者其他端口。

HTTP三点注意事项:

lHTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。

lHTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

客户端发送一个HTTP请求到服务器的请求消息包括以下格式:

l请求行(requestline)

l请求头部(header)

l空行

l请求数据

四个部分组成

下图给出了请求报文的一般格式。

客户端请求:

GET/hello.txtHTTP/1.1

User-Agent:curl/7.16.3libcurl/7.16.3OpenSSL/0.9.7lzlib/1.2.3

Host:www.example.com

Accept-Language:en,mi

HTTP响应也由四个部分组成,分别是:

l状态行

l消息报头

l响应正文

HTTP/1.1200OK

Date:Mon,27Jul200912:28:53GMT

Server:Apache

Last-Modified:Wed,22Jul200919:15:56GMT

ETag:"34aa387-d-1568eb00"

Accept-Ranges:bytes

Content-Length:51

Vary:Accept-Encoding

Content-Type:text/plain

根据HTTP标准,HTTP请求可以使用多种请求方法。

HTTP1.0定义了三种请求方法:GET,POST和HEAD方法。

HTTP1.1新增了五种请求方法:OPTIONS,PUT,DELETE,TRACE和CONNECT方法。

序号

方法

描述

1

GET

请求指定的页面信息,并返回实体主体。

2

HEAD

类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头

3

POST

向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。

POST请求可能会导致新的资源的建立和/或已有资源的修改。

4

PUT

从客户端向服务器传送的数据取代指定的文档的内容。

5

DELETE

请求服务器删除指定的页面。

6

CONNECT

HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

7

OPTIONS

允许客户端查看服务器的性能。

8

TRACE

回显服务器收到的请求,主要用于测试或诊断。

当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(serverheader)用以响应浏览器的请求。

HTTP状态码的英文为HTTPStatusCode。

下面是常见的HTTP状态码:

l200-请求成功

l301-资源(网页等)被永久转移到其它URL

l404-请求的资源(网页等)不存在

l500-内部服务器错误

HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:

HTTP状态码分类

分类

分类描述

1**

信息,服务器收到请求,需要请求者继续执行操作

2**

成功,操作被成功接收并处理

3**

重定向,需要进一步的操作以完成请求

4**

客户端错误,请求包含语法错误或无法完成请求

5**

服务器错误,服务器在处理请求的过程中发生了错误

HTTP状态码列表:

HTTP状态码列表

状态码

状态码英文名称

中文描述

100

Continue

101

SwitchingProtocols

切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议

200

OK

请求成功。一般用于GET与POST请求

201

Created

已创建。成功请求并创建了新的资源

202

Accepted

已接受。已经接受请求,但未处理完成

203

Non-AuthoritativeInformation

204

NoContent

无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档

205

ResetContent

重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域

206

PartialContent

部分内容。服务器成功处理了部分GET请求

300

MultipleChoices

多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择

301

MovedPermanently

永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替

302

Found

临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI

303

SeeOther

查看其它地址。与301类似。使用GET和POST请求查看

304

NotModified

未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源

305

UseProxy

使用代理。所请求的资源必须通过代理访问

306

Unused

已经被废弃的HTTP状态码

307

TemporaryRedirect

临时重定向。与302类似。使用GET请求重定向

400

BadRequest

客户端请求的语法错误,服务器无法理解

401

Unauthorized

请求要求用户的身份认证

402

PaymentRequired

保留,将来使用

403

Forbidden

服务器理解请求客户端的请求,但是拒绝执行此请求

404

NotFound

服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面

405

MethodNotAllowed

客户端请求中的方法被禁止

406

NotAcceptable

服务器无法根据客户端请求的内容特性完成请求

407

ProxyAuthenticationRequired

408

RequestTime-out

409

Conflict

服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突

410

Gone

客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置

411

LengthRequired

服务器无法处理客户端发送的不带Content-Length的请求信息

412

PreconditionFailed

客户端请求信息的先决条件错误

413

RequestEntityTooLarge

由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息

414

Request-URITooLarge

请求的URI过长(URI通常为网址),服务器无法处理

415

UnsupportedMediaType

服务器无法处理请求附带的媒体格式

416

Requestedrangenotsatisfiable

客户端请求的范围无效

417

ExpectationFailed

服务器无法满足Expect的请求头信息

500

InternalServerError

服务器内部错误,无法完成请求

501

NotImplemented

服务器不支持请求的功能,无法完成请求

502

BadGateway

充当网关或代理的服务器,从远端服务器接收到了一个无效的请求

503

ServiceUnavailable

由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中

504

GatewayTime-out

充当网关或代理的服务器,未及时从远端服务器获取请求

505

HTTPVersionnotsupported

服务器不支持请求的HTTP协议的版本,无法完成处理

Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些Asp网页点击的结果却是下载到的一个文件或一张图片的原因。

文件扩展名

Content-Type(Mime-Type)

.*(二进制流,不知道下载文件类型)

application/octet-stream

.tif

image/tiff

.001

application/x-001

.301

application/x-301

.323

text/h323

.906

application/x-906

.907

drawing/907

.a11

application/x-a11

.acp

audio/x-mei-aac

.ai

application/postscript

.aif

audio/aiff

.aifc

.aiff

.anv

application/x-anv

.asa

text/asa

.asf

video/x-ms-asf

.asp

text/asp

.asx

.au

audio/basic

.avi

video/avi

.awf

application/vnd.adobe.workflow

.biz

text/xml

.bmp

application/x-bmp

.bot

application/x-bot

.c4t

application/x-c4t

.c90

application/x-c90

.cal

application/x-cals

.cat

application/vnd.ms-pki.seccat

.cdf

application/x-netcdf

.cdr

application/x-cdr

.cel

application/x-cel

.cer

application/x-x509-ca-cert

.cg4

application/x-g4

.cgm

application/x-cgm

.cit

application/x-cit

.class

java/*

.cml

.cmp

application/x-cmp

.cmx

application/x-cmx

.cot

application/x-cot

.crl

application/pkix-crl

.crt

.csi

application/x-csi

.css

text/css

.cut

application/x-cut

.dbf

application/x-dbf

.dbm

application/x-dbm

.dbx

application/x-dbx

.dcd

.dcx

application/x-dcx

.der

.dgn

application/x-dgn

.dib

application/x-dib

.dll

application/x-msdownload

.doc

application/msword

.dot

.drw

application/x-drw

.dtd

.dwf

Model/vnd.dwf

application/x-dwf

.dwg

application/x-dwg

.dxb

application/x-dxb

.dxf

application/x-dxf

.edn

application/vnd.adobe.edn

.emf

application/x-emf

.eml

message/rfc822

.ent

.epi

application/x-epi

.eps

application/x-ps

.etd

application/x-ebx

.exe

.fax

image/fax

.fdf

application/vnd.fdf

.fif

application/fractals

.fo

.frm

application/x-frm

.g4

.gbr

application/x-gbr

.

application/x-

.gif

image/gif

.gl2

application/x-gl2

.gp4

application/x-gp4

.hgl

application/x-hgl

.hmr

application/x-hmr

.hpg

application/x-hpgl

.hpl

application/x-hpl

.hqx

application/mac-binhex40

.hrf

application/x-hrf

.hta

application/hta

.htc

text/x-component

.htm

text/html

.html

.htt

text/webviewhtml

.htx

.icb

application/x-icb

.ico

image/x-icon

application/x-ico

.iff

application/x-iff

.ig4

.igs

application/x-igs

.iii

application/x-iphone

.img

application/x-img

.ins

application/x-internet-signup

.isp

.IVF

video/x-ivf

.java

.jfif

image/jpeg

.jpe

application/x-jpe

.jpeg

.jpg

application/x-jpg

.js

application/x-javascript

.jsp

.la1

audio/x-liquid-file

.lar

application/x-laplayer-reg

.latex

application/x-latex

.lavs

audio/x-liquid-secure

.lbm

application/x-lbm

.lmsff

audio/x-la-lms

.ls

.ltr

application/x-ltr

.m1v

video/x-mpeg

.m2v

.m3u

audio/mpegurl

.m4e

video/mpeg4

.mac

application/x-mac

.man

application/x-troff-man

.math

.mdb

application/msaccess

application/x-mdb

.mfp

application/x-shockwave-flash

.mht

.mhtml

.mi

application/x-mi

.mid

audio/mid

.midi

.mil

application/x-mil

.mml

.mnd

audio/x-musicnet-download

.mns

audio/x-musicnet-stream

.mocha

.movie

video/x-sgi-movie

.mp1

audio/mp1

.mp2

audio/mp2

.mp2v

video/mpeg

.mp3

audio/mp3

.mp4

.mpa

video/x-mpg

.mpd

application/vnd.ms-project

.mpe

.mpeg

video/mpg

.mpg

.mpga

audio/rn-mpeg

.mpp

.mps

.mpt

.mpv

.mpv2

.mpw

.mpx

.mtx

.mxp

application/x-mmxp

.net

image/pnetvue

.nrf

application/x-nrf

.nws

.odc

text/x-ms-odc

.out

application/x-out

.p10

application/pkcs10

.p12

application/x-pkcs12

.p7b

application/x-pkcs7-certificates

.p7c

application/pkcs7-mime

.p7m

.p7r

application/x-pkcs7-certreqresp

.p7s

application/pkcs7-signature

.pc5

application/x-pc5

.pci

application/x-pci

.pcl

application/x-pcl

.pcx

application/x-pcx

.pdf

application/pdf

.pdx

application/vnd.adobe.pdx

.pfx

.pgl

application/x-pgl

.pic

application/x-pic

.pko

application/vnd.ms-pki.pko

.pl

application/x-perl

.plg

.pls

audio/scpls

.plt

application/x-plt

.png

image/png

application/x-png

.pot

application/vnd.ms-powerpoint

.ppa

.ppm

application/x-ppm

.pps

.ppt

application/x-ppt

.pr

application/x-pr

.prf

application/pics-rules

.prn

application/x-prn

.prt

application/x-prt

.ps

.ptn

application/x-ptn

.pwz

.r3t

text/vnd.rn-realtext3d

.ra

audio/vnd.rn-realaudio

.ram

audio/x-pn-realaudio

.ras

application/x-ras

.rat

application/rat-file

.rdf

.rec

application/vnd.rn-recording

.red

application/x-red

.rgb

application/x-rgb

.rjs

application/vnd.rn-realsystem-rjs

.rjt

application/vnd.rn-realsystem-rjt

.rlc

application/x-rlc

.rle

application/x-rle

.rm

application/vnd.rn-realmedia

.rmf

application/vnd.adobe.rmf

.rmi

.rmj

application/vnd.rn-realsystem-rmj

.rmm

.rmp

application/vnd.rn-rn_music_package

.rms

application/vnd.rn-realmedia-secure

.rmvb

application/vnd.rn-realmedia-vbr

.rmx

application/vnd.rn-realsystem-rmx

.rnx

application/vnd.rn-realplayer

.rp

image/vnd.rn-realpix

.rpm

audio/x-pn-realaudio-plugin

.rsml

application/vnd.rn-rsml

.rt

text/vnd.rn-realtext

.rtf

application/x-rtf

.rv

video/vnd.rn-realvideo

.sam

application/x-sam

.sat

application/x-sat

.sdp

application/sdp

.sdw

application/x-sdw

.sit

application/x-stuffit

.slb

application/x-slb

.sld

application/x-sld

.slk

drawing/x-slk

.smi

application/smil

.smil

.smk

application/x-smk

.snd

.sol

text/plain

.sor

.spc

.spl

application/futuresplash

.spp

.ssm

application/streamingmedia

.sst

application/vnd.ms-pki.certstore

.stl

application/vnd.ms-pki.stl

.stm

.sty

application/x-sty

.svg

.swf

.tdf

application/x-tdf

.tg4

application/x-tg4

.tga

application/x-tga

application/x-tif

.tiff

.tld

.top

drawing/x-top

.torrent

application/x-bittorrent

.tsd

.txt

.uin

application/x-icq

.uls

text/iuls

.vcf

text/x-vcard

.vda

application/x-vda

.vdx

application/vnd.visio

.vml

.vpg

application/x-vpeg005

.vsd

application/x-vsd

.vss

.vst

application/x-vst

.vsw

.vsx

.vtx

.vxml

.wav

audio/wav

.wax

audio/x-ms-wax

.wb1

application/x-wb1

.wb2

application/x-wb2

.wb3

application/x-wb3

.wbmp

image/vnd.wap.wbmp

.wiz

.wk3

application/x-wk3

.wk4

application/x-wk4

.wkq

application/x-wkq

.wks

application/x-wks

.wm

video/x-ms-wm

.wma

audio/x-ms-wma

.wmd

application/x-ms-wmd

.wmf

application/x-wmf

.wml

text/vnd.wap.wml

.wmv

video/x-ms-wmv

.wmx

video/x-ms-wmx

.wmz

application/x-ms-wmz

.wp6

application/x-wp6

.wpd

application/x-wpd

.wpg

application/x-wpg

.wpl

application/vnd.ms-wpl

.wq1

application/x-wq1

.wr1

application/x-wr1

.wri

application/x-wri

.wrk

application/x-wrk

.ws

application/x-ws

.ws2

.wsc

text/scriptlet

.wsdl

.wvx

video/x-ms-wvx

.xdp

application/vnd.adobe.xdp

.xdr

.xfd

application/vnd.adobe.xfd

.xfdf

application/vnd.adobe.xfdf

.xhtml

.xls

application/vnd.ms-excel

application/x-xls

.xlw

application/x-xlw

.xml

.xpl

.xq

.xql

.xquery

.xsd

.xsl

.xslt

.xwd

application/x-xwd

.x_b

application/x-x_b

.sis

application/vnd.symbian.install

.sisx

.x_t

application/x-x_t

.ipa

application/vnd.iphone

.apk

application/vnd.android.package-archive

.xap

application/x-silverlight-app

协议本质是双方约定好的一种传输规则,为了让传输数据的双方节点能建立连接,按照约定去传输和解析数据

THE END
1.js的三大核心组成部分js三大核心js的三大核心组成部分 一,Js的三大核心组成部分 1.ECMAScript2.DOM(document objectmodel)3.BOM(browser object document ) (1)ECMA是(欧洲计算机制造商协会)它规定了js的语法标准。 (2)DOM是文档对象模型,规定了文档的显示结构,可以轻松地删除、添加和替换节点https://blog.csdn.net/qq_15243963/article/details/77986054
2.CPU是计算机的核心它是由什么组成的3、中央处理器(CPU),是电子计算机的主要设备之一,电脑中的核心配件。其功能主要是解释计算机指令以及处理计算机软件中的数据。CPU是计算机中负责读取指令,对指令译码并执行指令的核心部件。 4、中央处理器主要包括两个部分,即控制器、运算器,其中还包括高速缓冲存储器及实现它们之间联系的数据、控制的总线。 5、电子计https://edu.iask.sina.com.cn/jy/3bAlscaFurL.html
3.著作权的核心组成部分是什么著作权的核心组成部分是什么 导读:著作权的核心内容是指著作权人的人身权和财产权。著作权是指文学、艺术、科学作品的作者对其作品享有的权利。著作权是知识产权的一种类型,它是由自然科学、社会科学以及文学、音乐、戏剧、绘画、雕塑、摄影和电影摄影等方面的作品组成。https://www.64365.com/zs/1301407.aspx
4.好利来的核心业务由两大部分组成:好利来的核心业务由两大部分组成: 1.饼店连锁系统:以连锁店的形式,主营生日蛋糕、西点、中点、面包等产品。截止目前,已在全国八十多个大中城市开设了近千家连锁店,建立了庞大的连锁经营体系。 2. 包装食品制造系统:主营产品为好利来牌月饼其他包装食品。目前在北京和沈阳建有大型现代化食品工厂。这两个食品工厂的生https://m.dianping.com/review/361265134
5.计算机硬件系统由五个基本部分组成,其中系统核心CPU又由()组成A. 营业额由堂食营业额、外带营业额和外卖营业额三个部分组成 B. 营业额的高低影响着门店的人员配置 C. 营业额=来单数×单均 D. 营业额的高低与TC无关 查看完整题目与答案 如何预计准确的日营业额呢?() ①查看过去前三周同一天营业额情况,以及起伏趋势; ②对照前一周营业额的起伏趋势; ③结合未来https://www.shuashuati.com/ti/fc182ec8d8144569a3d10b3848b1fea2.html
6.网络安全威胁情报标准收集整理1.它的主要组成部分 STIX Core Objects:STIX核心对象定义了一组标准化的数据模式和属性,用于描述威胁情报的各个方面,如攻击者、目标、威胁情报等。 STIX Relationship Objects:STIX关系对象定义了不同核心对象之间的关联关系,如攻击者与目标之间的关系、攻击方法与攻击实例之间的关系等。 https://www.51cto.com/article/786412.html
7.自考马克思主义基本原理概论复习大纲及必背重点整理唯物辩证法(Materialist Dialectics),是一种研究自然、社会、历史和思维的哲学方法;是辩证法的三种基本历史形式之一;是由马克思首先提出,经其他马克思主义者(比较突出的如恩格斯、列宁、托洛茨基、M Z D等)发展而形成的一套世界观、认识论和方法论的思想体系;是马克思主义哲学的核心组成部分。 https://www.eol.cn/baokao/zk-wyw/2023111210499.html
8.跑步费劲吃力?练好核心肌群也能轻松跑腰腹前后左右上下的肌肉组成了核心肌群,他们一起工作让核心又稳固又有劲儿。稳固代表的是稳定性,有劲儿代表的是力量。因此,真正的核心能力包括核心稳定性和核心力量两部分组成。核心稳定性主要靠腰腹深层肌肉产生,而核心力量主要靠腰腹浅层肌肉实现。二者相辅相成,核心力量的增强有助于稳定性的提高,核心稳定性的提https://www.chunyuyisheng.com/pc/article/131289/
9.肉团团购6月19线上招商第二部分(收入组成)这里是总代—核心—联创 收入组成部分。 三级别:总代~核心~联创 2总代: 零售:每单利润10-20之间、根据不同产品不同利润,多卖多赚 团队收入~直接代理每单,你都有1-2块接单费 3核心利润比总代多3-6元之间,15个直属代理?自己一起一个月做10万营业额,考核核心、核心收入=自己零售?市场https://www.meipian.cn/309x5now
10.PLC技术的电气工程自动化控制运用论文(精选16篇)信息的共享,而共享的首要前提就是要保证电气工程自动化的开放性,让数据信息的共享有良好的途径,电气工程自动化是建立在外界有效的接口上的,借助于计算机联网实现与外界信息的交流共享,将信息和资源进行有序的交换和共享,从而实现电气工程自动化系统对工程进行远程监督的控制,而这些也是电气工程自动化技术的核心组成部分https://biyelunwen.yjbys.com/fanwen/zidonghua/681669.html