第五章
-
对于HTTP的POST请求方式,用户提交的表单数据位于HTTP请求的哪一部分?(B)
A 请求头中
B 请求正文中
资源表示在请求主体中发送,放在首部后面。也就是说,它会按顺序发送以下4项:
(1)一个起始行,包括方法、路径和查询字符串,以及HTTP版本。
(2)一个HTTP首部。
(3)一个空行(两个连续的回车/换行对)。
(4)请求正文。
例如,下面这个POST请求向服务器发送表单数据:
POST /cgi-bin/register.pl HTTP 1.0 Date: Sun, 27 Apr 2013 12:32:36 Host: www. cafeaulait. org Content-type: application/x-WWW- form-urlencoded Content -length: 54 username=Elliotte+Harold&email =elharo%4oibiblio. org
在这个例子中,主体包含一个application/x www-form -urlencoded数据,但并不只有这一种可能。一般来讲,主体可以包含任意的字节。不过,HTTP首部要包括两个字段来指定主体的性质:
一个Content-length字段,指定主体中有多少字节(前面的例子中为54字节)。
一个Content-type字段,指定类型的MIME媒体类型(前面的例子中内容类型为application/x-www-form-urlencoded)。
java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析 -
HTTP请求中的请求头与请求正文之间必须以空行隔开,同样,HTTP响应中的响应头与响应正文之间也必须以空行隔开。这句话是否正确?(A)
A 正确
B 不正确
http响应格式
HTTP应答与HTTP请求相似,HTTP响应也由3个部分构成,分别是:
(1)状态行
(2)响应头(Response Header)
(3)空格
(4)响应正文
在接收和解释请求消息后,服务器会返回一个HTTP响应消息。
状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。
java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析 -
在HTTP响应结果中,哪个状态代码表示响应成功?(C)
A 404
B 305
C 200
D 500
200~299的状态码表示成功
300~399的状态码指资源重定向
400~499的状态码指客户端请求出错
500~599的状态码指服务端出错
-
ServerSocket与Socket都有一个SO_TIMEOUT选项,它们的作用是否相同?(B)
A 相同
B 不同
ServerSocket中,SO_TIMEOUT:表示等待客户连接的超时时间。
Socket中,SO_TIMEOUT:表示接收数据时的等待超时时间。
- 对于以下程序代码:
ServerSocket serverSocket=new ServerSocket(8000); serverSocket.setReuseAddress(true);
哪个说法是正确的?(C)
A 以上代码运行时出错
B 以上代码编译时出错
C 以上代码尽管编译和运行不会出错,但对SO_REUSEADDR选项的设置无效
D 以上说法都不正确
SO_REUSEADDR:表示是否允许重用服务器所绑定的地址,应该在绑定在任何端口之前设置。此题已经在SO_REUSEADDR之前绑定了端口,所以设置无效。
改写:
ServerSocket serverSocket=new ServerSocket(); serverSocket.setReuseAddress(true); //设置ServerSocket的选项 serverSocket.bind(new InetSocketAddress(8000)); //与8000端口绑定
-
如何判断一个ServerSocket已经与特定端口绑定,并且还没有被关闭? (B)
A boolean isOpen=serverSocket.isBound();
B boolean isOpen=serverSocket.isBound() && !serverSocket.isClosed();
C boolean isOpen=serverSocket.isBound() && serverSocket.isConnected();
D boolean isOpen=!serverSocket.isClosed();
(1)测试一个ServerSocket是否被关闭:isClosed()
(2)测试一个ServerSocket是否绑定到过某个端口上:isBound()
(3)测试一个ServerSocket是否打开
public static Boolean isOpen(ServerSocket ss){ return ss.isBound()&& !ss.isClosed(); }
-
关于ServerSocket构造方法的backlog参数,以下哪些说法是正确的?(ABCDF)
A backlog参数用来显式设置操作系统中的连接请求队列的长度。
B 如果没有设置backlog参数,那么连接请求队列的长度由操作系统决定。
C 当服务器端的连接请求队列已满,客户端就无法建立与服务器的连接。
D 如果backlog参数的值大于操作系统限定的队列的最大长度,那么backlog参数被忽略。
E 连接请求队列直接由ServerSocket创建并管理。
F ServerSocket的accept()方法从连接请求队列中取出连接请求。
serverSocket = new ServerSocket(port,3); //连接请求队列的长度为3
ServerSocket构造方法的backlog参数用来显式设置连接请求队列的长度,它将覆盖操作系统限定的队列的最大长度(一般为50)。
在以下几种情况,仍然会采用操作系统限定的队列的最大长度:
(1)backlog参数的值大于操作系统限定的队列的最大长度。
(2)backlog参数的值小于或等于0。
(3)在ServerSocket构造方法中没有设置backlog参数。
管理客户连接请求的任务是由操作系统来完成的。操作系统把这些连接请求存储在一个先进先出的队列中。许多操作系统限定了队列的最大长度,一般为50。当队列中的连接请求达到了队列的最大容量时,服务器进程所在的主机会拒绝新的连接请求。只有当服务器进程通过ServerSocket的accept()方法从队列中取出连接请求,使队列腾出空位时,队列才能继续加入新的连接请求。
小结:
-
HTTP交互的基本过程
客户端与服务器的80端口(或其它端口)连接TCP连接
客户端向服务器发送HTTP请求(Request)
务器向客户端发送HTTP响应(Response)
服务器关闭TCP连接
-
注意:
HTTP协议是无状态的
一个Request对应且只对应一个Response
Response是被动的
-
实现并发服务器的三种方式:
(1)为每个客户分配一个工作线程。
(2)利用JDK的Java类库中现成的线程池,由它的工作线程来为客户服务。
(3)采用非阻塞的方式来实现服务器。
- 为每个客户分配一个线程
java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析 - 使用JDK类库提供的线程池
java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析
第六章
-
默认情况下,SocketChannel对象处于什么模式?(A)
A 阻塞模式
B 非阻塞模式
解析:配置非阻塞模式,
serverChannel. configureBlocking(false);
- 对于以下代码:
int n=socketChannel.read(byteBuffer); //假定n>=0 byteBuffer.flip();
假定执行socketChannel.read(byteBuffer)方法前,byteBuffer的容量、极限和位置分别为c、l和p,执行完以上代码后,byteBuffer的容量、极限和位置分别是多少?(B)
A 容量为c,极限为l,位置为p+n
B 容量为c,极限为p+n,位置为0
C 容量为l,极限为p+n,位置为0
D 容量为c,极限为p+n,位置为p+n
在Java NIO编程中,对缓冲区操作常常需要使用 java.nio.Buffer中的 flip()方法。
Buffer 中的 flip() 方法涉及到 Buffer 中的capacity、position、limit三个概念。
(1)capacity:在读/写模式下都是固定的,就是我们分配的缓冲大小(容量)。
(2)limit:在写模式下表示最多能写入多少数据,此时和capacity相同。在读模式下表示最多能读多少数据,此时和缓存中的实际数据大小相同。
(3)position:类似于读/写指针,表示当前读(写)到什么位置。
flip():Buffer有两种模式,写模式和读模式。在写模式下调用flip()之后,Buffer从写模式变成读模式,那么limit就设置成了position当前的值(即当前写了多少数据),postion会被置为0,以表示读操作从缓存的头开始读。也就是说调用flip()之后,读/写指针position指到缓冲区头部,并且设置了最多只能读出之前写入的数据长度(而不是整个缓存的容量大小)。
java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析 上三个属性的关系为:容量>=极限>=位置>=0
扩展:
public final Buffer mark()和public final Buffer reset():用于标记位置将来回头重读或重写
public final Buffer clear():“清空”缓冲区,把极限设为容量,再把位置设为0。
public final Buffer rewind():不改变极限,把位置设为0
public final Buffer flip():把极限设为位置,再把位置设为0。
public final int remaining():返回Buffer的剩余容量,取值等于极限-位置
public final boolean hasRemaining():Buffer是否还有剩余容量
除了向Buffer里写数据的方法put()之外,Buffer的其它方法都不会改变Buffer中现有的值
-
在哪些情况,SelectionKey对象会失效?(ACD)
A 程序调用SelectionKey的cancel()方法。
B 程序调用SelectionKey的close()方法。
C 关闭与SelectionKey关联的Channel。
D 与SelectionKey关联的Selector被关闭。
在SelectionKey对象的有效期间,Selector会一直监控与SelectionKey对象相关的事件,如果事件发生,就会把SelectionKey对象加入到selected-keys集合中。
在以下情况,SelectionKey对象会失效,这意味着Selector再也不会监控与它相关的事件:
(1)程序调用SelectionKey的cancel()方法。
(2)关闭与SelectionKey关联的Channel。
(3)与SelectionKey关联的Selector被关闭。
-
SocketChannel可能发生哪些事件?(BCD)
A SelectionKey.OP_ACCEPT:接收连接就绪事件
B SelectionKey.OP_CONNECT:连接就绪事件。
C SelectionKey.OP_READ:读就绪事件。
D SelectionKey.OP_WRITE:写就绪事件。
SelectionKey类的一些静态常量表示事件类型
(1)ServerSocketChannel只可能发生一种事件:
SelectionKey.OP_ACCEPT:接收连接就绪事件
(2)SocketChannel可能发生以下三种事件:
SelectionKey.OP_CONNECT:连接就绪事件
SelectionKey.OP_READ:读就绪事件
SelectionKey.OP_WRITE:写就绪事件
-
在服务器程序中,线程在哪些情况可能会进入阻塞状态?(CDE)
A 线程执行Socket的getInputStream()方法获得输入流。
B 线程执行Socket的getOutputStream()方法获得输出流。
C 线程执行ServerSocket的accept()方法。
D 线程从Socket的输入流读入数据。
E 线程向Socket的输出流写一批数据。
客户端线程进入阻塞的场景
(1)建立连接时
请求与服务器建立连接时,会进入阻塞状态,直到连接成功。
(2)读数据时
从Socket的输入流读入数据时,如果没有足够的数据,就会进入阻塞状态,直到读到了足够的数据(“足够数据”对不同的read()方法有不同含义);或到达输入流的末尾;或者出现了异常。
(3)写数据时
线程向Socket的输出流写一批数据时,可能会进入阻塞状态,直到写出了所有的数据;或者出现异常。
(4)关闭Socket时
当调用Socket的setSoLinger()方法设置了关闭Socket的延迟时间,那么当线程执行Socket的close()方法时,会进入阻塞状态,直到底层Socket发送完所有剩余数据;或者超过了setSoLinger()方法设置的延迟时间。
服务器线程进入阻塞的场景
(1)线程执行ServerSocket的accept()方法,等待客户的连接,直到接收到了客户连接,才从accept()方法返回。
(2)线程从Socket的输入流读入数据时, 如果输入流没有足够的数据,就会进入阻塞状态。
(3)线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。
-
线程执行Selector对象的select(long timeout)方法时进入阻塞状态,在哪些情况,线程会从select()方法中返回?(ABDE)
A 至少有一个SelectionKey的相关事件已经发生。
B 其他线程调用了Selector对象的wakeup()方法。
C 与Selector对象关联的一个SocketChannel对象被关闭。
D 当前执行select()方法的线程被其他线程中断。
E 超出了等待时间。
public int select(long timeout)throws IOException
采用阻塞的工作方式,返回相关事件已经发生的SelectionKey对象的数目,如果一个也没有,就进入阻塞状态,直到出现以下情况之一才返回:
(1)至少一个SelctionKey对象的相关事件已经发生
(2)其它线程调用了这个Selector对象的wakeup()方法
(3)当前执行select()方法的线程被其它线程中断
(4)超出了等待时间(不会抛出异常)
小结:
7. 非阻塞IO通道技术模型
8. 服务器轮询线程
3. Java支持Socket编程的类