天天看点

java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析

第五章

  1. 对于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习题解析
  2. HTTP请求中的请求头与请求正文之间必须以空行隔开,同样,HTTP响应中的响应头与响应正文之间也必须以空行隔开。这句话是否正确?(A)

    A 正确

    B 不正确

    http响应格式

    HTTP应答与HTTP请求相似,HTTP响应也由3个部分构成,分别是:

    (1)状态行

    (2)响应头(Response Header)

    (3)空格

    (4)响应正文

    在接收和解释请求消息后,服务器会返回一个HTTP响应消息。

    状态行由协议版本、数字形式的状态代码、及相应的状态描述,各元素之间以空格分隔。

    java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析
  3. 在HTTP响应结果中,哪个状态代码表示响应成功?(C)

    A 404

    B 305

    C 200

    D 500

    200~299的状态码表示成功

    300~399的状态码指资源重定向

    400~499的状态码指客户端请求出错

    500~599的状态码指服务端出错

  4. ServerSocket与Socket都有一个SO_TIMEOUT选项,它们的作用是否相同?(B)

    A 相同

    B 不同

    ServerSocket中,SO_TIMEOUT:表示等待客户连接的超时时间。

    Socket中,SO_TIMEOUT:表示接收数据时的等待超时时间。

  5. 对于以下程序代码:
    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端口绑定
               
  6. 如何判断一个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();
    	}
               
  7. 关于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()方法从队列中取出连接请求,使队列腾出空位时,队列才能继续加入新的连接请求。

小结:

  1. HTTP交互的基本过程

    客户端与服务器的80端口(或其它端口)连接TCP连接

    客户端向服务器发送HTTP请求(Request)

    务器向客户端发送HTTP响应(Response)

    服务器关闭TCP连接

  2. 注意:

    HTTP协议是无状态的

    一个Request对应且只对应一个Response

    Response是被动的

  3. 实现并发服务器的三种方式:

    (1)为每个客户分配一个工作线程。

    (2)利用JDK的Java类库中现成的线程池,由它的工作线程来为客户服务。

    (3)采用非阻塞的方式来实现服务器。

  4. 为每个客户分配一个线程
    java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析
  5. 使用JDK类库提供的线程池
    java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析

第六章

  1. 默认情况下,SocketChannel对象处于什么模式?(A)

    A 阻塞模式

    B 非阻塞模式

    解析:配置非阻塞模式,

    serverChannel. configureBlocking(false);

  2. 对于以下代码:
    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中现有的值

  3. 在哪些情况,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被关闭。

  4. 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:写就绪事件

  5. 在服务器程序中,线程在哪些情况可能会进入阻塞状态?(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()方法返回或异常中断。

  6. 线程执行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通道技术模型

java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析

8. 服务器轮询线程

java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析

3. Java支持Socket编程的类

java网络编程5、6章习题解析第五章第六章下一节: java网络编程7、8、9习题解析

下一节: java网络编程7、8、9习题解析

继续阅读