目录
OSI七层网络模型与TCP/IP四层网络模型
TCP协议中的三次握手和四次挥手
wireshark抓包分析http:https://blog.csdn.net/dengjili/article/details/85850267
滑动窗口
ACK 表示下一次期望收到的开始数据,window表示窗口大小,滑动窗口目的是控制发送速度,以免接收方的缓存不够大导致溢出,同时控制流量也可以避免网络拥塞。
TCP通信中的缓冲区
首先,对于TCP通信来说,每个TCP Socket的内核中都有一个发送缓冲区和一个接收缓冲区,TCP的全双工的工作模式及TCP的滑动窗口就是依赖于这两个独立的Buffer和该Buffer的填充状态。
接收缓冲区把数据缓存到内核,若应用进程一直没有调用Socket的read方法进行读取,那么该数据会一直被缓存在接收缓冲区内。不管进程是否读取Socket,对端发来的数据都会经过内核接收并缓存到Socket的内核接收缓冲区。
read索要做的工作,就是把内核接收缓冲区中的数据复制到应用层用户的Buffer里。
进程调用Socket的send发送数据的时候,一般情况下是讲数据从应用层用户的Buffer里复制到Socket的内核发送缓冲区,然后send就会在上层返回。换句话说,send返回时,数据不一定会被发送到对端。
单工,单向传输数据,对应java代码
服务端
public class ScoketServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
// 启动一个应用
serverSocket = new ServerSocket(8888);
// 等待缓冲区的数据,BIO模型
Socket accept = serverSocket.accept();
// 字节流转换为字符流
BufferedReader br = new BufferedReader(new InputStreamReader(accept.getInputStream()));
System.out.println(br.readLine());
} catch (IOException e) {
} finally {
// 关闭资源
if (serverSocket != null) {
try {
serverSocket.close();
} catch (IOException e) {
}
}
}
}
}
客户端
public class ScoketClient {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("localhost", 8888);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("hello 张三");
// 强制发送缓存区数据,可能缓冲区数据不满
bw.flush();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
双工,双向传输数据,对应java代码
服务端
public class ScoketServerDeplex {
static ServerSocket serverSocket = null;
public static void main(String[] args) {
try {
// 启动一个应用
serverSocket = new ServerSocket(8888);
new Thread(() -> {
while (true) {
Socket socket;
try {
socket = serverSocket.accept();
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
// 读
String serverData = dis.readUTF();
System.out.println("服务端接收到数据:" + serverData);
// 写
dos.writeUTF("hello 李四");
dos.flush();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
System.out.println("服务器启动成功...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
客户端
public class ScoketClientDeplex {
public static void main(String[] args) {
Socket socket = null;
try {
socket = new Socket("localhost", 8888);
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
// 发送
dos.writeUTF("hello 张三");
dos.flush();
// 接收
String serverData = dis.readUTF();
System.out.println("客户端接收到数据:" + serverData);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
UDP通信
组播Multicas
服务端
public class MulticastServer {
public static void main(String[] args) {
// 组播ip地址: 224.0.0.0-239.255.255.255
try {
InetAddress group = InetAddress.getByName("224.8.8.8");
MulticastSocket socket = new MulticastSocket();
for (int i = 0; i < 10; i++) {
String data = "Hello 李四";
byte[] bytes = data.getBytes();
socket.send(new DatagramPacket(bytes, bytes.length, group, 8888));
TimeUnit.SECONDS.sleep(2);
}
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
客户端
public class MulticastClient {
public static void main(String[] args) {
// 组播ip地址: 224.0.0.0-239.255.255.255
try {
InetAddress group = InetAddress.getByName("224.8.8.8");
MulticastSocket socket = new MulticastSocket(8888);
socket.joinGroup(group);
byte[] buf = new byte[128];
while (true) {
DatagramPacket msgPacket = new DatagramPacket(buf, buf.length);
socket.receive(msgPacket);
byte[] data = msgPacket.getData();
String serverData = new String(data, 0, data.length);
System.out.println("接收到服务器数据:" + serverData);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}