MOOC 个人学习笔记

# 1. 基础知识

# port:端口,0-65535

  • 0~1023, OS 已经占用了,80 是 Web,23 是 telnet
  • 1024~65535,一般程序可使用 (谨防冲突)
  • 两台机器通讯就是在 IP+Port 上进行的
  • 在 Windows/Linux/Mac 上都可以通过 netstat -an 来查询

# 通讯协议:TCP 和 UDP

  • TCP(Transmission Control Protocol)
    • 传输控制协议,面向连接的协议
    • 两台机器的可靠无差错的数据传输
    • 双向字节流传递
  • UDP(User Datagram Protocol)
    • 用户数据报协议,面向无连接协议
    • 不保证可靠的数据传输
    • 速度快,也可以在较差网络下使用

# 2.UDP 编程

  • UDP:无连接无状态的通讯协议
  • 发送方发送消息,如果接收方刚好在目的地,则可以接受。如果不在,那这个消息就丢失了
  • 发送方也无法得知是否发送成功
  • UDP 的好处就是简单,节省,经济

# 主要类

  • DatagramSocket:通讯的数据管道
    • send 和 receive 方法
    • (可选,多网卡) 绑定一个 IP 和 Port
  • DatagramPacket
    • 集装箱:封装数据
    • 地址标签:目的地 IP+Port
  • 无主次之分
  • 接收方必须早于发起方执行
// 构造本机 3000 端口 Socket
DatagramSocket ds=new DatagramSocket(3000);
// 构造本机随机端口 Socket
DatagramSocket ds=new DatagramSocket();
//Socket 关闭
ds.close();
// 构造接收 Packet
byte [] buf=new byte[1024];
DatagramPacket dp=new DatagramPacket(buf,1024);
// 构造发送 Packet,目标为 127.0.0.1:3000
String str="hello world";
DatagramPacket dp=new DatagramPacket(str.getBytes(),str.length(),
                                     InetAddress.getByName("127.0.0.1"),3000);
// 接收消息放入 dp,否则阻塞
ds.receive(dp);
// 发送 dp 消息至指定端口
ds.send(dp);

# 3.TCP 编程

  • TCP 协议:有链接、保证可靠的无误差通讯
  • ①服务器:创建一个 ServerSocket,等待连接
  • ②客户机:创建一个 Socket,连接到服务器
  • ③服务器:ServerSocket 接收到连接,创建一个 Socket 和客户的 Socket 建立专线连接,后续服务器和客户机的对话 (这一对 Socket) 会在一个单独的线程(服务器端)上运行
  • ④服务器的 ServerSocket 继续等待连接,返回①
Error: Navigating frame was detached

# 主要类

  • ServerSocket: 服务器码头
    • 需要绑定 port
    • 如果有多块网卡,需要绑定一个 IP 地址
  • Socket: 运输通道
    • 客户端需要绑定服务器的地址和 Port
    • 客户端往 Socket 输入流写入数据,送到服务端
    • 客户端从 Socket 输出流取服务器端过来的数据
    • 服务端反之亦然
// 创建服务器 Socket
ServerSocket ss = new ServerSocket(8001); // 驻守在 8001 端口
// 服务器创建 Socket
Socket s = ss.accept(); // 阻塞,等到有客户端连接上来
//Socket 关闭
s.close();
ss.close();
// 服务器创建流
InputStream ips = s.getInputStream(); // 有人连上来,打开输入流
OutputStream ops = s.getOutputStream(); // 打开输出流
// 流关闭
ips.close();
ops.close();
// 服务器发送消息
ops.write("Hello, Client!".getBytes()); // 输出一句话给客户端
// 服务器接收消息
BufferedReader br = new BufferedReader(new InputStreamReader(ips));
System.out.println("Client said: " + br.readLine());
//******************************************************************************
// 客户端建立连接
Socket s = new Socket(InetAddress.getByName("127.0.0.1"), 8001); // 需要服务端先开启
//Socket 关闭
s.close();
// 同一个通道,服务端的输出流就是客户端的输入流;服务端的输入流就是客户端的输出流
InputStream ips = s.getInputStream(); // 开启通道的输入流
BufferedReader brNet = new BufferedReader(new InputStreamReader(ips));
System.out.println(brNet.readLine());
brNet.close();
OutputStream ops = s.getOutputStream(); // 开启通道的输出流
DataOutputStream dos = new DataOutputStream(ops);
dos.writeBytes(strWord);
dos.close();

# 客户端与服务端

  • 服务端等待响应时,处于阻塞状态
  • 服务端可以同时响应多个客户端
  • 服务端每接受一个客户端,就启动一个独立的线程与之对应
  • 客户端或者服务端都可以选择关闭这对 Socket 的通道

# 4.HTTP 编程

# 网页访问

  • 网页是特殊的网络服务 (HTTP, Hypertext Transfer Protocol)
    • 在浏览器输入 URL 地址
    • 浏览器将连接到远程服务器上 (IP+80Port)
    • 请求下载一个 HTML 文件下来,放到本地临时文件夹中
    • 在浏览器显示出来

# 访问方式

  • GET:从服务器获取资源到客户端
  • POST:从客户端向服务器发送数据
  • PUT:上传文件
  • DELETE:删除文件
  • HEAD:报文头部
  • OPTIONS:询问支持的方法
  • TRACE:追踪路径
  • CONNECT:用隧道协议连接代理

# java.net 包

  • 支持模拟成浏览器的方式去访问网页
  • URLConnection
    • 获取资源的连接器
    • 根据 URL 的 openConnection () 方法获得 URLConnection
    • connect 方法,建立和资源的联系通道
    • getInputStream 方法,获取资源的内容
// 建立连接
String urlName = "http://www.baidu.com";
URL url = new URL(urlName);
URLConnection connection = url.openConnection(); 
connection.connect();
// 头部信息
Map<String, List<String>> headers = connection.getHeaderFields();
// 基础属性
System.out.println("getContentType: " + connection.getContentType());
System.out.println("getContentLength: " + connection.getContentLength());
System.out.println("getContentEncoding: " + connection.getContentEncoding());
System.out.println("getDate: " + connection.getDate());
System.out.println("getExpiration: " + connection.getExpiration());
System.out.println("getLastModifed: " + connection.getLastModified());
// 获得 HTML 流
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));

# 5.HTTP 编程(基于 HttpClient)

  • JDK HTTP Client (JDK 自带,从 9 开始)
  • Apache HttpComponents 的 HttpClient (Apache 出品)

# JDK HttpClient

  • JDK 9 新增,JDK10 更新,JDK11 正式发布
  • java.net.http 包・取代 URLConnection
  • 支持 HTTP/1.1 和 HTTP/2
  • 实现大部分 HTTP 方法
  • 主要类
    • HttpClient
    • HttpRequest
    • HttpResponse
// 获得 HTML 流
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("http://www.baidu.com")).build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

# HttpComponents

  • hc.apache.org, Apache 出品
  • 从 HttpClient 进化而来
  • 是一个集成的 Java HTTP 工具包
    • 实现所有 HTTP 方法:get/post/put/delete
    • 支持自动转向
    • 支持 https 协议
    • 支持代理服务器等
// 获得 HTML 流
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet("http://www.baidu.com");
String srtResult = "";
try {
    HttpResponse httpResponse = httpClient.execute(httpGet);
    if(httpResponse.getStatusLine().getStatusCode() == 200){
        srtResult = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");// 获得返回的结果                
        System.out.println(srtResult);
    }else
    {
        //Exception TODO
    }
} catch (IOException e) {
    e.printStackTrace();
}finally {
    try {
        httpClient.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}