少女祈祷中...

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
  • 无主次之分
  • 接收方必须早于发起方执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//构造本机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继续等待连接,返回①
graph LR
c1[Client1
Socket]--客户端发出连接-->ss[ServerSocket] c2[Client2
Socket]--客户端发出连接-->ss[ServerSocket] ss--服务器接受请求并创建新的Socket-->s1[为Client1创
建的Socket] ss--服务器接受请求并创建新的Socket-->s2[为Client2创
建的Socket] c1--两个Socket间建立专线连接-->s1 c2--两个Socket间建立专线连接-->s2

主要类

  • ServerSocket: 服务器码头
    • 需要绑定port
    • 如果有多块网卡,需要绑定一个IP地址
  • Socket: 运输通道
    • 客户端需要绑定服务器的地址和Port
    • 客户端往Socket输入流写入数据,送到服务端
    • 客户端从Socket输出流取服务器端过来的数据
    • 服务端反之亦然
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//创建服务器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方法,获取资源的内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//建立连接
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
1
2
3
4
5
//获得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协议
    • 支持代理服务器等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//获得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();
}
}