第二课:Socket通讯与HTTP服务器

课程网站:

  • http://ss.sysu.edu.cn/~pml/dct/2_http.html

相关文章:

  • 第一课:Java进阶与Socket通讯实验
  • 第二课:Socket通讯与HTTP服务器
  • 第三课:Java Web 编程原理
  • 第四课:RESTful Webservice 编程

列出网络七层协议的名称,用一句话分别解释 传输层(TCP/UDP) 与 网络层(IP) 的功能。

网络七层协议:

  • 应用层
  • 表示层
  • 会话层
  • 传输层
  • 网络层
  • 数据链路层
  • 物理层

传输层(TCP/UDP)的功能:

  • 数据传送,不关心数据含义,进程间通信。
  • 弥补高层(上3层)要求与网络层(基于下3层)数据传送服务质量间的差异(差错率、差错恢复能力、吞吐率、延时、费用等),对高层屏蔽网络层的服务的差异,提供稳定和一致的界面。

网络层(IP)的功能:
TCP/IP协议栈的网络层主要负责处理主机到主机的通信,决定数据包如何交付:是交给网关(路由器)还是交给本地端口。

参考资料:
http://www.cnblogs.com/zfyouxi/archive/2014/06/22/3801899.html
http://blog.csdn.net/thisispan/article/details/7543362

Socket 在哪一层? 解释端口号的作用。

套接字(socket)编程接口是从顶上三层(网络协议的应用层,即应用层,表示层和会话层)进入传输层的接口。

IP地址和网络服务是一对多的关系。端口号可以用于区分不同的网络服务。比如21端口分配给FTP(文件传输协议)服务,25端口分配给SMTP(简单邮件传输协议)服务,80端口分配给HTTP服务,135端口分配给RPC(远程过程调用)服务等等。

参考资料:
http://www.360doc.com/content/14/0804/15/12928831_399366221.shtml
http://baike.baidu.com/link?url=wdcJm3ZrwklgGCu8foaXl0ftCUWM_IcQRWYV1XRTXcu222iJlu0qdg_VgVnqw9ONsQSyf3w3wugDPqmVXRNgia

TCP 也称 流式 Socket。 与流式文件存在联系吗?

流式文件中构成文件的基本单位是字符,流式文件是有序字符的集合,其长度为该文件所包含的字符个数,所以又称为字符流文件。流式文件无结构,且管理简单,用户可以方便地对其进行操作。源程序、目标代码等文件属于流式文件。

而TCP协议是一个传输协议,两者是完全不同领域的东西。

两者唯一可能的联系就是用TCP协议传输流式文件。因为几乎所有的文件都是由TCP协议传输的。

参考资料:
http://baike.sogou.com/v10273711.htm

阅读图2-8,连接 Socket 和 数据 Socket 相同吗?


第二课:Socket通讯与HTTP服务器_第1张图片
图2-8

为什么编程时,我们通常只自定义 4 位数的端口号?

在 Java 程序中使用socket 进行通信可支持在一台主机上运行的单个服务程序为多个不同的客户程序提供服务。为实现这一目标,服务程序将选定一个固定的端口号对外发布服务客户程序则必须先按约定的主机与端口号向服务程序发送一个要求建立连接的请求(这些请求称为连接请求),申请建立一个到服务程序的连接。
服务程序在收到某一客户程序的连接请求后,并不是利用对外发布的那个端口号建立与该客户程序的连接,而是另外分配一个新的端口号建立与客户程序之间的连接,原端口号仍用于监听其他客户程序的连接请求。这一通信模式保证了服务程序对外公布的端口号仅用于处理客户程序要求建立连接的请求,不会因为该端口因长期处理客户程序的服务请求而导致其他客户程序的阻塞。

端口号的范围在065535之间。01023范围的端口号是周知端口号(well-known port number),是受限制的。Windows通常限制5000以上端口,要开启5000以上得修改注册表。所有通常是用4位数的端口号。

参考资料:
https://support.microsoft.com/zh-cn/kb/196271

文档中提到工厂方法。请用 UML 图画出 InetAddress , Inet4Address 和 Inet6Address 三者关系。

类InetAddress 采用工厂方法设计模式的好处是使客
户程序可透明地使用IPv4 协议和IPv6 协议。采用IPv4 协议时,工厂方法返回Inet4Address 的实例;采用IPv6 协议时, 工厂方法返回Inet6Address 的实例。Inet4Address 和Inet6Address 都是InetAddress 的子类。

第二课:Socket通讯与HTTP服务器_第2张图片
InetAddress,Inet4Address 和 Inet6Address的关系图

对照图2.9,写出每个步骤的关键代码。


第二课:Socket通讯与HTTP服务器_第3张图片
图2.9 流式Socket通信过程

侦听并等待连接:

ServerSocket listenSocket = new ServerSocket(Integer.parseInt(args[0]));
System.out.println("服务程序正在监听端口" + args[0]);
Socket socket = listenSocket.accept();

请求并建立连接:

Socket socket = new Socket(args[0], Integer.parseInt(args[1]));
System.out.println("当前socket 信息:" + socket);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

服务器建立连接:

PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader
(socket.getInputStream()));

客户端发信息给服务器:

BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("返回:" + in.readLine());
}
stdIn.close();

服务器接收处理信息:

String message;
while ((message = in.readLine()) != null) {
System.out.println("收到请求:" + message);
out.println(message.toUpperCase());
}

关闭连接:

out.close();
in.close();
socket.close();

(!)修改 MTEchoServer, 用 java 的 List<> 对象管理客户端连接的服务线程。当连接断开后,服务线程只是挂起。在新连接请求时,如果有挂起的服务线程,直接为新连接服务。

import java.io.*;
import java.net.*;
import java.util.ArrayList;

public class MTEchoServer {
    public static void main(String[] args) throws IOException {
        ArrayList servers = new ArrayList();

        if (args.length != 1) {
            System.out.println("用法:MTServer <端口号>");
            return ;
        }

        ServerSocket ss = new ServerSocket(Integer.parseInt(args[0]));
        System.out.println("服务程序正在监听端口:" + args[0]);
        for (int i = 0; i < servers.size(); i++) {
            if (servers.get(i).getState() == Thread.State.WAITING) {
                servers.get(i).notify();
                continue;
            }
            EchoThread s = new EchoThread(ss.accept());
            s.start();
            servers.add(s);
        }
    }
}

class EchoThread extends Thread {
    Socket socket;
    EchoThread(Socket s) {
        socket = s;
    }
    public void run() {
        System.out.println("正在为客户程序提供服务:" + socket);
        try {
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String message;
            while ((message = in.readLine()) != null) {
                System.out.println(socket + "请求:" + message);
                out.println(message.toUpperCase());
            }
            out.close();
            in.close();
            socket.close();
            synchronized (this) {
                try {
                    this.wait();
                } catch (InterruptedException exc) {
                    exc.printStackTrace();
                }
            }
        } catch (IOException exc) {
            exc.printStackTrace();
        }
    }
}

参考资料:
线程挂起与恢复

写出 RFC 和 IETF 的全称。 给出HTTP1.1协议的RFC编号以及全文的网址。

Request For Comments(RFC),是一系列以编号排定的文件。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件。目前RFC文件是由Internet Society(ISOC)赞助发行。基本的互联网通信协议都有在RFC文件内详细说明。RFC文件还额外加入许多的论题在标准内,例如对于互联网新开发的协议及发展中所有的记录。因此几乎所有的互联网标准都有收录在RFC文件之中。
国际互联网工程任务组(The Internet Engineering Task Force,简称 IETF)是一个公开性质的大型民间国际团体,汇集了与互联网架构和互联网顺利运作相关的网络设计者、运营者、投资人和研究人员,并欢迎所有对此行业感兴趣的人士参与。

参考资料:
百度百科 RCF
百度百科 IETF
IETF官网 RFC文档

阅读 Daytime 协议开发,简单解释图 2-11 的含义。它对程序阅读的作用。


第二课:Socket通讯与HTTP服务器_第4张图片
图 2-11 程序DaytimeTCP 客户端与服务器程序类图

DaytimeServer2是基于TCPDaytime服务器程序,首先通过ServerSocket 类的实例化产生流
Socket,并由MyStreamSocket 类的实例对象的accept()方法监听客户端请求,等待客户端连
接。当收到客户端请求后,由sendMessage()方法返回消息给客户端。

MyStreamSocket类继承Socket 类,setStreams()方法得到数据输入流InputStream 与输出流OutputStream , sendMessage() 方法发送数据流,receiveMessage() 接收数据流。

DaytimeClient2是基于TCPDaytime 客户端程序,客户端程序从命令行取得服务端的地址与端
口,通过客户端帮助类DaytimeClientHelper2 的getTimestamp()方法向服务端发送请求并接收
响应消息。

DaytimeClientHelper2客户端帮助类创建MyStreamSocket类的实例对象mySocket,由实例对象的
receiveMessage()方法接收服务端的响应消息。

图2-11说明了这几个类之间的关系。DaytimeClient2用到了DaytimeClientHelper2的实例,DaytimeClientHelper2用到了MyStreamSocket的实例,DaytimeServer2用到了ServerSocket和MyStreamSocket的实例,而MyStreamSocket继承自Socket类。用这样的UML图可以使得类与类之间的关系更加清楚。

编程序经常会编写xxHelper 类,请描述 DaytimeTCP 程序中,DaytimeClientHelper2类发挥的作用。

有模块化思想,实现了类的封装性,有利于代码的维护和复用

运行 java 版本 HttpServer。设计3个curl 指令,测试程序的三种输出响应,给出控制台输入与输出。

由于默认是80端口,被占用,于是改成了2000端口。

ServerSocket ss = new ServerSocket((args.length == 0) ? 2000 : Integer.parseInt(args[0]));
第二课:Socket通讯与HTTP服务器_第5张图片
打开HttpServer客户端

在服务器文件夹下添加一个index.html,输入curl localhost:2000

第二课:Socket通讯与HTTP服务器_第6张图片
curl localhost:2000

输入一个不存在的网页,例如curl localhost:2000/notfound

第二课:Socket通讯与HTTP服务器_第7张图片
404

就出现了404的提示。由于Java的编码问题,出来了一堆乱码。但是可以看懂有404。如果直接用浏览器打开,则没有这个问题。

如果用Post方法,例如输入curl -d "400 Test" localhost:2000

第二课:Socket通讯与HTTP服务器_第8张图片
400

则出现了400提示,表示非法请求。


(!)阅读 “课后完成设计实验 HTTP 学号尾数为奇数同学完成.pdf”
improveHTTPServer 设计者的目标是什么?用了哪些手段改进了程序设计?

  • 改进单线程服务器为多线程服务器,实现并发处理请求;
  • 综合应用设计模式(工厂方法、模板方法、策略模式、Facade 模式、责任链模式等),构建可扩展的Web 服务器。

如果要实现 POST 方法,如何改程序(改哪个类)?

……

(!!)尝试给出处理不同请求方法的 UML 设计图。
……

你可能感兴趣的:(第二课:Socket通讯与HTTP服务器)