传统Socket网络编程
Server端
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class SocketServer {
public static void main(String[] args) throws Exception {
ServerSocket serverSocket = new ServerSocket(9000);
while(true) {
Socket socket = serverSocket.accept(); // 在这里会阻塞住,一直等待别人跟建立连接
new Worker(socket).start();
}
// 如果有一个客户端跟他发起了TCP三次握手,尝试建立一个连接
// 这里就会构建出来一个Socket,这个Socket就代表了跟某个客户端的一个TCP连接,Socket连接
// 如果有人要跟你建立TCP连接,接下来基于TCP协议来传输数据,发送一个一个的TCP包过来
// 此时他会必须是跟你的某个服务器程序的端口号建立的连接
// 客户端跟你的ServerSocket之间,互相传递3次握手的TCP包,连接就建立,互相交换了一些数据
}
static class Worker extends Thread {
Socket socket;
public Worker(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
// 接下来,一旦建立了TCP连接之后
// 客户端就会通过IO流的方式发送数据过来,无限的流
// 所以说底层的TCP协议会把流式的数据拆分为一个一个的TCP包,包裹在IP包里,以太网包
// 最后通过底层的网络硬件设备以及以太网的协议,发送数据给你发送过来
InputStreamReader in = new InputStreamReader(socket.getInputStream());
OutputStream out = socket.getOutputStream();
char[] buf = new char[1024 * 1024];
int len = in.read(buf);// read会有一个阻塞的效果,他会阻塞在这里尝试读取数据出来
// Socket的输入流,相当于就是不停的读取人家通过TCP协议发送过的一个一个的TCP包
// 把TCP包的数据通过IO输入流的方式提供给你
// 你就可以通过IO输入流读取的方式把TCP包的数据读出来放入JVM内存的一个缓冲数组中
while(len != -1) {
String request = new String(buf, 0, len);
System.out.println("[" + Thread.currentThread().getName()
+ "]服务端接收到了请求:" + request);
out.write("收到,收到".getBytes());
len = in.read(buf);
// 你需要反复的去读取socket流传输过来的数据
// 因为人家是不停的用流的方式发送数据过来的,你不需要不停的读取
// buf才1kb,可能你才读取了1kb的数据
// 后面可能还跟了几百kb的数据,所以需要你不停的读取
// 他的意思就是说,你通过IO流发送响应数据回去
// 此时在底层会把你的响应数据拆分为一个一个的TCP包,回传回去
// 客户端就可以接受到你发送的TCP包
}
out.close();
in.close();
socket.close(); // 走TCP四次挥手连接就直接断开了
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Client端
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class SocketClient {
public static void main(String[] args) throws Exception {
for(int i = 0; i < 10; i++) {
new Thread() {
public void run() {
try {
Socket socket = new Socket("localhost", 9000);
// 此处应该是会找DNS服务查找域名对应的IP地址
// 接下来需要跟那个ip地址上的9000端口的服务器程序进行TCP三次握手,建立连接
// 这个时候他就会构造一个三次握手中的第一次握手的TCP包
// 在这个TCP包里放入三次握手需要的数据
// 把这个TCP包封装在IP包里,是有对应的目标的IP地址,再封装在以太网包里
// 通过底层的硬件设备走以太网协议出去,路由器,人家通过IP地址查找路由表,确定下一个路由器的位置
// 查找下一个路由器的mac地址写入到以太网包头,走下一个子网广播出去
// 通过这种方式层层转发,一直到对应的服务器上去
// 服务器接收到三次握手的第一次握手的TCP包
// 就会回传第二次握手的TCP包给这个客户端的程序,客户端再次发送第三次握手的TCP包过去
// 三次握手成功,TCP连接建立起来了
InputStreamReader in = new InputStreamReader(socket.getInputStream());
OutputStream out = socket.getOutputStream();
char[] buf = new char[1024 * 1024];
while(true) {
try {
out.write("你好".getBytes()); // 发送数据流,底层拆分为一个一个的TCP包发过去
int len = in.read(buf);
if(len != -1) {
String response = new String(buf, 0, len);
System.out.println("[" + Thread.currentThread().getName()
+ "]客户端接收到了响应:" + response);
}
Thread.sleep(1000);
} catch(Exception e) {
e.printStackTrace();
in.close();
out.close();
socket.close(); // 其实就会走TCP四次挥手断开连接
}
}
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
}
}