TCP 协议下的 C/S
UDP : 不可靠的、无连接的、发送/接受数据时,是以数据报为单位的
TCP: 可靠的、有链接的、发送数据时是以数据流的形式
可靠/不可靠 : 可靠并不能代表就一定能通过网络发送成功。而是发送的数据尽可能的保证成功,即使失败了,发送方也有感知
面向字节流: 一个连接可以只传递一组 请求-响应:
发送“你好\r\n”
接受是 “你”“好””\r“"\n",当收到EOS时,请求读取结束了
一个连接可以传递多组 请求-响应
发送”请求1请求2“
接收时 “请” “求1” “请” “求2”
如何把多个请求分开?
- 先长度,再数据
- 固定长度
- 特殊字符分割
网络连接时序图
值得强调的是,在这种情况下,有多个客户端且一个客户端没有发送给服务器请求,那么别的客户端就不会收到响应,发生阻塞。
这种情况下就要使用多线程。
import java.util.*;
import java.net.*;
import java.io.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static class ServiceMan extends Thread {
private final Socket socket;
ServiceMan(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
// 获取输入流
InputStream is = socket.getInputStream();
// 封装成 Scanner
Scanner scanner = new Scanner(is, "UTF-8");
// 使用 \r\n 进行分割的方式,读取一个请求
// 等着第一个 Client 发送请求
String request = scanner.nextLine(); // nextLine() 把 \r\n 已经去掉
System.out.println("收到请求: " + request);
// 业务处理
String response = request;
// 发送响应,也许要使用 \r\n 跟在后边,进行分割
OutputStream os = socket.getOutputStream();
// 封装成 PrintWriter
PrintWriter writer = new PrintWriter(
new OutputStreamWriter(os, "UTF-8")
);
// 发送响应
writer.println(response); // println 会帮我们在后边增加 \r\n
writer.flush();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws IOException {
// 开一家店
ServerSocket serverSocket = new ServerSocket(9898);
ExecutorService threadPool = Executors.newFixedThreadPool(20);
// 循环处理业务
// 主线程只负责接待 —— 连接连接的过程
while (true) {
Socket socket = serverSocket.accept(); // 虽然有 4 个Client 连接,socket 代表的是第一个Client
/*
// 所有业务处理的过程,交给线程去处理
new ServiceMan(socket).start();
*/
// 各个线程之间,没有数据共享(主线程和工作线程之间共享 socket)
// 所以天生是线程安全的
threadPool.execute(new ServiceMan(socket));
}
}
}
import java.util.*;
import java.io.*;
import java.net.*;
import java.util.concurrent.TimeUnit;
public class Client {
public static void main(String[] args) throws IOException, InterruptedException {
Socket socket = new Socket("127.0.0.1", 9898);
Scanner console = new Scanner(System.in);
System.out.print("请输入请求> ");
String request = console.nextLine();
OutputStream os = socket.getOutputStream();
PrintWriter writer = new PrintWriter(
new OutputStreamWriter(os, "UTF-8")
);
writer.println(request);
writer.flush();
InputStream is = socket.getInputStream();
Scanner scanner = new Scanner(is, "UTF-8");
String response = scanner.nextLine(); // 对象没有响应,就一直等
System.out.println(response);
socket.close();
}
}
HTTP协议
重点协议——应用层上非常广泛的一组HTTPS
Hyper Text Transfer Protocol : 超文本传输协议
1.0/1.1版本的时候,HTTP还是建立在TCP基础上 —— HTTP协议需要可靠性作为基础的
http协议的标准端口: 80
URL —— Unique Resource Location
是在互联网上唯一表示一个资源
格式: