标志位 URG:紧急指针(urgent pointer)有效。 ACK:确认序号有效。 PSH:接收方应该尽快将这个报文交给应用层。 RST:重置连接。 SYN:发起一个新连接。 FIN:释放一个连接。 tcp三次握手 为什么需要三次握手,为了初始化Sequence Number的初始值 隐患 解决隐患 四次挥手 为什么有timewait状态 确保被动关闭的一方能够收到ack包,若未收到,则重发,刚好是两个msl的时间。 避免新旧连接混淆,有些路由器会缓存数据包。 为什么要4次挥手 全双工,发送方和接收方都各自需要FiN报文和ACK报文 TCP的滑动窗口 窗口计算(可以通过窗口对发送端进行流量限制)
与TCP的区别 面向连接(三次握手、四次挥手) /无连接 可靠(握手、确认、重传)/不可靠 有序(序列号,到达可能是无序的,但是tcp会进行排序)/无序 速度慢(创建连接、保证有效、可靠)/速度快(主要用于在线视频、多人广播、多人在线游戏) 重量级(20字节头)/8字节头
使用TCP和UDP分别完成 客户端发送一个字符串到服务端,服务端接收到后打印出字符串的长度,并将长度返回到客户端。
tcp public class TCPClient { public static void main(String[] args) throws IOException { //创建socket指定连接的主机和端口 Socket socket = new Socket("127.0.0.1", 65000); InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); //写入字符串 outputStream.write(new String("hello world").getBytes()); //获取服务器返回的信息 byte[] bytes = new byte[1034]; int ch = inputStream.read(bytes); //将信息转为字符串 String s = new String(bytes, 0, ch); System.out.println(s); outputStream.close(); inputStream.close(); socket.close(); } } public class TCPServer { public static void main(String[] args) throws IOException { //创建socket并绑定65000端口 ServerSocket serverSocket = new ServerSocket(65000); while (true){ //监听该端口,知道客户端返回连接信息才返回 Socket socket = serverSocket.accept(); //执行业务逻辑 new LengthCalculator(socket).start(); } } } public class LengthCalculator extends Thread{ private Socket socket; public LengthCalculator(Socket socket) { this.socket = socket; } @Override public void run() { try { //获得输入输出流 InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); //获取信息 byte[] bytes = new byte[1024]; //数组长度 int ch = inputStream.read(bytes); //转为字符串 String s = new String(bytes, 0, ch); //向输出流中写入字符串长度 outputStream.write(String.valueOf(s.length()).getBytes()); System.out.println(s); //关闭资源 outputStream.close(); inputStream.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } UDP public class UDPClient { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(); byte[] bytes = "hello".getBytes(); //将ip地址封装成InetAddress对象 InetAddress[] addresses = InetAddress.getAllByName("127.0.0.1"); DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, addresses[0], 65001); socket.send(packet); byte[] data = new byte[100]; DatagramPacket receivedPacket = new DatagramPacket(data, 100); socket.receive(receivedPacket); System.out.println(new String(receivedPacket.getData(),0,receivedPacket.getLength())); } }public class UDPServer { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(65001);
//用于存储收到的内容 DatagramPacket packet = new DatagramPacket(new byte[100], 100); //将收到的内容转为packet socket.receive(packet); //获取真正的内容 byte[] data = packet.getData(); String s = new String(data, 0, packet.getLength()); System.out.println(s); String len = String.valueOf(s.length()); byte[] lenBytes = len.getBytes(); //发送给客户端 //从packet中获取地址,端口.封装成packet对象 DatagramPacket toClient = new DatagramPacket(lenBytes, 0, lenBytes.length, packet.getAddress(), packet.getPort()); socket.send(toClient); }}
在这里插入代码片输入url后的访问流程
DNS解析TCP连接(三次握手)发送HTTP请求服务器处理请求,并把带有HTML文本的结果通过HTTP报文返回浏览器渲染页面关闭连接(关闭连接和释放页面没有先后)四次挥手常见HTTP状态码 三位数组成
第一位数:响应类别 get/post区别 cookie/session cooke: session