TCP协议基本概念
- 连接安全,性能相对不如UDP
- 能适应弱网环境,通过滑动窗口来控制接收数据的能力,UDP不管网络环境,有就发,可能会造成大量阻塞
- 同时也会通知客户端当前能接收多大量数,并且数据接收到哪里了,客户端会根据这两个信息进行发送数据
TCP三次握手 与 四次挥手
-
报文介绍 (1). ACK = 确认标识 (2). SYN = 连接请求标识 (3). FIN = 结束标识 (4). SEQ = 一个随机数,即seq_number = x -
三次握手流程 (1). 第一次握手:client端向server端发送码SYN = 1, 并随机产生一个数字,即seq_number = x的数据包 (2). 第二次握手:server端进行响应,会返回一个ACK = x + 1, 并生成一个随机数y给客户端 (3). 第三次握手:client端收到响应最终确认发送ACK = y+1, 并开始建立连接。至此3次握手结束 -
四次挥手流程 (1). (2). (3).
TCP洪泛攻击
- TCP洪泛攻击是在第二次握手的时候
- 大量的虚假ip会像服务器发起连接请求。
- 服务器接收到后全部会进行响应。
- 但由于客户端的这个ip根本不存在,所以根本没法响应,此时服务端就会一直等待,直到超时
- 这种情况会造成大量连接阻塞等待,无法释放,导致正常连接请求无法进来
- 解决方案1:缩短连接请求的过期时间,让占用连接的虚假ip尽快的超时
- 解决方案2:列入黑名单,或者购买高防服务器
TCP客户端编写(可以接收服务端响应的数据)
/**
* TCO发送端
*
* 1. 创建发送端socket对象(创建连接)---做3此握手,确认服务器端存在,再传输数据
* 2. 获取输出流对象
* 3. 发送数据
* 4. 接收服务端响应的数据
* 5. 释放资源
*/
public class TcpSend {
public static void main(String[] args) throws IOException {
Scanner sc = new Scanner(System.in);
while(true){
String input = sc.nextLine();
if("666".equals(input)){
break;
}
// 1. 创建发送端socket对象(创建连接)---做3此握手,确认服务器端存在,再传输数据
// 参数1: 接收server端的服务ip
// 参数2: 端口号port
Socket socket = new Socket(InetAddress.getByName("hbz.test.udp.socket"), 8090);
// 2. 获取输出流对象
OutputStream outputStream = socket.getOutputStream();
// 3. 发送数据
outputStream.write(input.getBytes());
System.out.println("发送成功");
// 4.接收server响应的数据
InputStream inputStream = socket.getInputStream();
byte[] data = new byte[1024];
int read = inputStream.read(data);
System.out.println("我客户端收到了服务端响应数据 :" + new String(data));
// 5. 释放资源
outputStream.close();
socket.close();
}
}
}
TCP服务端编写(可以接收服务端响应的数据)–可以多线程
/**
* TCO接收端(可以多线程,如果写成单线程,没重新走到serverSocket.accept();这句,那么服务端是收不到客户端的连接请求的)
*
* 1. 创建接收端socket对象(创建连接)
* 2. 监听(阻塞:如果建立连接失败,程序一直阻塞)
* 3. 获取输入流对象
* 4. 获取数据
* 5. 输出数据
* 6. 相应给客户端数据
* 7. 释放资源
*/
public class TcpServer {
public static void main(String[] args) throws IOException {
// 1.创建接收端socket对象(创建连接)
// 参数2: 端口号port
ServerSocket serverSocket = new ServerSocket(8090);
while (true){
// 2.监听(阻塞:如果建立连接失败,程序一直阻塞)
Socket socket = serverSocket.accept();
// 多线程可以同时接收多个客户端的内容, 一般情况不允许直接new Thread(),这只是例子
new Thread(()->{
try (InputStream inputStream = socket.getInputStream();){
// 4. 获取数据
byte[] bytes = new byte[1024];
int len = inputStream.read(bytes);
// 5. 输出数据
System.out.println("服务器端接收的数据:" + new String(bytes) + ", 长度 : " + len);
// 6. server回应数据给client
OutputStream outputStream = socket.getOutputStream();
String response = "我收到了,内容是:" + new String(bytes);
outputStream.write(response.getBytes());
System.out.println("已给客户端回应");
}catch (Exception e){
e.getMessage();
}finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
if("666".equals("7")){
break;
}
}
// 7. 释放资源
serverSocket.close();
}
}
|