网络协议及tcp协议详解(代码片段)

xupeidong xupeidong     2023-04-17     789

关键词:

问题来源:面试中面试官会看到你的简历上写着熟悉网络、http、tcp协议等,那你真的了解他吗?今天它来了

 

一、网络协议:

技术图片

 

层次说明:
第七层:应用层(http
为操作系统或网络应用程序提供访问网络服务的接口。
第六层:表示层
处理两个通信系统中交换信息的表示方式。为上层用户解决用户信息的语法问题。包括数据格式交换、数据加密与解密、数据压缩与终端类型的转换。
第五层:会话层
在两个节点之间建立端连接。为端系统的应用程序之间提供了对话控制机制。会话层不参与具体的传输,它提供包括访问验证和会话管理在内的建立和维护应用之间通信的机制。如服务器验证用户登录便是由会话层完成的。
第四层:传输层(tcp
为会话层用户提供一个端到端的可靠、透明和优化的数据传输服务机制。
第三层:网络层
网络层的任务就是选择合适的网间路由和交换结点, 确保数据及时传送。
第二层:数据链路层
在物理层提供比特流服务的基础上,建立相邻结点之间的数据链路,通过差错控制提供数据帧在信道上无差错的传输,并进行各电路上的动作系列。数据链路层在不可靠的物理介质上提供可靠的传输。该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。
第一层:物理层
物理层的主要功能是利用物理传输介质为数据链路层提供物理连接,以便透明的传送比特流。
 
二、tcp协议:
技术图片

 

 

说说TCP三次握手的过程?

第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。

第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。

第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

TCP的报文格式是怎么样的?
重要字段:

序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

确认序号:Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:

  1. URG:紧急指针(urgent pointer)有效。
  2. ACK:确认序号有效。
  3. PSH:接收方应该尽快将这个报文交给应用层。
  4. RST:重置连接。
  5. SYN:发起一个新连接。
  6. FIN:释放一个连接。

为什么要三次握手,两次不可以吗?
为了实现可靠数据传输,TCP协议的通信双方都必须维护一个序列号,以标识发送出去的数据包中,哪些是已经被对方收到的。三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。如果只是两次握手,至多只有连接发起方的起始序列号能被确认,另一方选择的序列号则得不到确认.

如果已经建立了连接,但是客户端突然出现故障了怎么办?
客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务端有一个保活计时器,每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,就关闭连接。

再说说TCP的四次挥手的过程?
由于TCP连接时全双工的,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭。

  1. 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
  2. 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
  3. 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
  4. 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

为什么要四次挥手,三次不可以吗?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

 

三、不使用API手动实现一个http的类:

服务端步骤:

|- WSAStartup函数初始化
|- 创建Socket
|- 用bind指定对象
|- listen设置监听
|- accept接收请求
|- send发送会话
|- closesocket关闭socket

 

客户端步骤:

|- WSAStartup函数初始化
|- 创建Socket
|- connect请求连接
|- send发送会话
|- closesocket关闭socket

 

服务端代码:

    SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
    int send_len = 0;
    int recv_len = 0;
    //定义服务端套接字,接受请求套接字
    SOCKET s_server;
    //服务端地址客户端地址
    SOCKADDR_IN server_addr;
    //初始化套接字库
    WSADATA wsadata;
    WSAStartup(0x22, &wsadata);    
    //填充服务端地址信息
    //填充服务端信息
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(80);
    std::string msgstr="";
    //创建套接字
    s_server = socket(AF_INET, SOCK_STREAM, 0);
    int result = bind(s_server,(struct sockaddr *) &server_addr,sizeof(server_addr));
    if (result == SOCKET_ERROR) /* 绑定失败 */
    
        closesocket(s_server);
        printf("[Web] Fail to bind, error = %d
", WSAGetLastError());
        return -1; 
    
    if (listen(s_server,SOMAXCONN)==-1) 
        int err = GetLastError();
        std::cout << "服务器启动失败!" << std::endl;
        std::cout << err << std::endl;
    
    else 
        std::cout << "服务器启动成功!" << std::endl;
    
    while(1)
        SOCKADDR_IN from_addr;   /* 客户端地址  */
        socklen_t from_len = sizeof(from_addr);
        std::string reponse_data="404";
        SOCKET acpt_soc = accept(s_server,(struct sockaddr *) &from_addr,&from_len);
        if (acpt_soc == INVALID_SOCKET) /* 接受失败 */
            int err = GetLastError();
            printf("接收失败1", WSAGetLastError());
            std::cout << err << std::endl;
            break; 
        
            char recv_buf [1025] = "";
            recv_len = recv(acpt_soc,recv_buf,1025, 0);
            if (recv_len < 0) 
            std::cout << "接收失败2!" << std::endl;
            else
            std::cout << "接收成功!" << std::endl;
            std::cout << recv_buf << std::endl;
            
            send_len = send(acpt_soc,recv_buf,strlen(recv_buf), 0);
            if (send_len < 0) 
                std::cout << "发送失败!" << std::endl;
                closesocket(acpt_soc);
            else
                std::cout << "发送成功!" << std::endl;
            
    
    //关闭套接字
    closesocket(s_server);
    //释放DLL资源
    WSACleanup();

客户端代码:

    SOCKET clientSocket=socket(AF_INET,SOCK_STREAM,0);
        //printf("客户端嵌套字已经打开!
");
    int send_len = 0;
    int recv_len = 0;
    //定义服务端套接字,接受请求套接字
    SOCKET s_server;
    //服务端地址客户端地址
    SOCKADDR_IN server_addr;
    //初始化套接字库
    WSADATA wsadata;
    WSAStartup(0x22, &wsadata);    
    //填充服务端地址信息
    //填充服务端信息
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(12580);
    string msgstr="";
    //创建套接字
    s_server = socket(AF_INET, SOCK_STREAM, 0);
    int nTimeout = 120000;
    //设置接收超时为1000ms
    if (SOCKET_ERROR == setsockopt(s_server, SOL_SOCKET, SO_RCVTIMEO, (char *)&nTimeout, sizeof(int)))
    
        fprintf(stderr, "Set SO_RCVTIMEO error !
");
    
    if (connect(s_server, (SOCKADDR *)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR) 
        cout << "服务器连接失败!" << endl;
        closesocket(s_server);
        //释放DLL资源
        WSACleanup();
        return 0;
    
    else 
        cout << "服务器连接成功!" << endl;
    
    //发送,接收数据
        cout << "开始传输桌面信息:"<< endl;
    while(1)
            char send_buf [1025] = "111";
            send_len = send(s_server,send_buf,strlen(send_buf), 0);
                if (send_len < 0) 
                    cout << "发送失败!" << endl;
                    closesocket(s_server);
                    //释放DLL资源
                    WSACleanup();
                    return 0;
                else
                    cout << "发送成功!" << endl;
                
                char recv_buf [1025] = "";
                recv_len = recv(s_server,recv_buf,1025, 0);
                if (recv_len < 0) 
                    cout << "接收失败!" << endl;
                    closesocket(s_server);
                    //释放DLL资源
                    WSACleanup();
                    return 0;
                else
                    cout <<recv_buf<< endl;
                    cout << "接收成功!" << endl;
                
    
    //关闭套接字
    closesocket(s_server);
    //释放DLL资源
    WSACleanup();

 

欢迎大家留言交流,一块成长进步。

[linux]linux网络之tcp协议详解(代码片段)

目录1.传输层2.端口号3.TCP协议3.1TCP协议的特性3.1.1面向连接3.1.2可靠传输3.1.3面向字节流3.2TCP报头3.3TCP连接管理及可靠性问题3.3.1可靠性3.3.2保证可靠性的机制3.3.3保证效率的机制3.3.3.1滑动窗口机制3.3.3.2拥塞控制3.4其它机制3.4.1延... 查看详情

tcp协议粘包问题详解(代码片段)

...执行Server端shell命令并拿到其执行结果的程序,而涉及到网络通信就必然会出现socket模块,关于 查看详情

网络基础知识-tcp/ip协议各层详解(代码片段)

TCP/IP简介  虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多。  计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM、Apple和Microsoft都有各自的网络协议... 查看详情

tcp网络协议的三次握手及代码释义(代码片段)

讲解TCP协议,我们首先要了解什么是网络通讯协议.1、网络通讯协议两台计算机要想在网络中互相通讯,就必须要遵守一定的规定,并且只有通讯双方同时遵守了这些规定,才能够实现数据的相互传输.而这些规定,便是由网络通讯协议... 查看详情

传输层——tcp(详解三路握手与四次挥手)(代码片段)

...靠传输、有流量控制、拥塞控制、面向字节流传输、提高网络利用率等诸多优点的协议。其最 查看详情

网络协议-http协议详解-https(代码片段)

HTTP的缺点HTTP协议设计的初衷就是简单方便,但是随着Web的发展和交互的复杂,也引入了一些安全性问题:通信使用明文,内容可能会被窃听:HTTP协议本身不具备加密功能,所以无法对通信整体(请求和响应的内容)进行加密,... 查看详情

❤️tcp通信传输协议详解❤️(java网络通信项目进阶二)(代码片段)

上篇教程回顾ServerSocket--监听客户端的连接,他的作用主要是建立一个连接 -ServerSocket-建立连接,拿到一个Socket-Telnet127.0.0.18888-客户端使用Telnet访问服务端建立连接-服务端可以拿到一个Socket的对象 -获取这个对象的输入输... 查看详情

tcp协议详解(代码片段)

...的状态变迁。TCP数据流:通过分析TCP数据流,我们可以从网络应用程序外部来了解应用层协议和通信双方交换的应用层数据。TCP数据流的控制:为了保证可靠传输和提高网络通信质量,内核需要对TCP数据流进行控制。 3.1TCP服... 查看详情

osi七层网络协议及tcp/udpc/s架构详解

OSI七层网络协议及TCP/UDP、C/S架构详解一、OSI七层网络、Linux四层网络模型1、为什么需要网络通信2、通讯设备有哪些3、什么是通信协议?作用是什么?二、OSI七层协议1、物理层2、数据链路层3、网络层4、传输层A)TCP协议1&... 查看详情

深入理解tcp协议及其源代码——connect及bindlistenaccept背后的“三次握手”(代码片段)

...议族中的位置如图1所示。它是专门为了在不可靠的互联网络上提供一个面向连接的且可靠的端到端(进程到进程)字节流而设计的。互联网络与单个网络不同,因为互联网络的不同部分可能有截然不同的拓扑、带宽、延迟、分... 查看详情

软件测试体系学习及构建-网络基础知识了解(代码片段)

网络基础知识了解1计算机网络定义2计算机网络分类3网络层次4OSI七层网络模型5部分层物理设备(举例)6TCP/IP模型6.1各层协议6.2IP协议6.3ICMP协议6.4ARP协议6.5UDP与TCP协议6.6TCP三次握手6.7应用层协议7端口8IP地址8.1含义8.2特点8... 查看详情

再谈http和https及tcp/udp/ip协议分析,面试官都惊讶的网络见解(代码片段)

一.再谈HTTP再理解协议的本质:双方的一种约定,规则,双方需要按照相同的一套处理机制(协议)进行处理应用层协议对应的是一个服务,FTP文件传输协议,NDS域名解析协议,HTTP超文本传输协议,这些是协议同时也对应着一... 查看详情

tcp包头详解(代码片段)

...的报文段,最大传输段大小(MSS)通常受该计算机连接的网络的数据链路层的最大传送单元(MTU)限制。之后TCP把数据包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。s 查看详情

tcp协议详解(图解tcp协议格式tcp的各种可靠传输机制)(代码片段)

目录1.TCP协议格式2.TCP的可靠传输机制2.1确认应答(ACK)机制2.2超时重传机制2.3连接管理机制2.4滑动窗口机制2.5流量控制机制2.6拥塞控制2.7延迟应答机制2.8捎带应答机制2.9保活定时器(TCP心跳包)3.TCP小结1.TCP协议格式如图... 查看详情

tcp协议详解(代码片段)

...输访问、远程登录等。远程登录TELNET使用TELNET协议提供在网络其它主 查看详情

初识socket(代码片段)

初始socket网络编程概念要想理解socket,就要先来理解TCP,UDP协议。TCP/IP(TransmissionControlProtocol/InternetProtocol)即传输控制协议/网间协议,定义了主机如何连入因特网及数据如何再它们之间传输的标准,TCP/IP是TCP和IP协议的合称,TCP/I... 查看详情

rtsp协议详解(代码片段)

...#xff01;协议主要规定定了一对多应用程序如何有效地通过IP网络传送多媒体数据。RTSP体系结位于RTP和RTCP之上 查看详情

网络安全暴力破解工具—九头蛇(hydra)使用详解及实战(代码片段)

目录使用方法案例分析暴破ssh登录密码环境介绍开始爆破破解成功测试登录各种协议破解汇总FTP协议破解http协议破解https协议破解路由器破解http-proxy协议破解smb破解 Windows远程桌面邮箱pop3telnet破解语音通讯工具teamspeakcisco 推荐... 查看详情