• 网络编程(二)——TCP协议、基于tcp协议的套接字socket


    TCP协议与基于tcp协议的套接字socket

    一、TCP协议(流式协议)

    1、可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包不必再分割。数据传输以数据流的形式传送

    2.(1)三次握手建链接
       (2)四次挥手断开链接
       (3)tcp协议的状态
       (4)syn洪水攻击与半连接池

    3、(1)三次握手建立链接、四次挥手断开链接(各种状态)

    SYN(synchronous建立联机)
    ACK(acknowledgement 确认)
    PSH(push传送)
    FIN(finish结束)
    RST(reset重置)
    URG(urgent紧急)

    三次握手 —— TCP协议提供可靠的连接服务,采用三次握手建立一个连接

    第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
    第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECD状态。
    第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。

    四次挥手 —— TCP采用四次挥手关闭连接

    第一次挥手:客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送,客户端A进入FIN_WAIT_1状态
    第二次挥手:服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。服务端B进入CLOSE_WAIT状态
    第三次挥手:服务端数据发送完毕以后,服务器B关闭与客户端A的连接,发送一个FIN给客户端A,服务端进入进入LAST_ACK状态
    第四次挥手:客户端A收到FIN后进入TIME_WAIT状态,接着发送一个ACK给服务端,确认序号为收到序号+1,服务端B进入CLOSED状态,完成四次挥手
    # 1.什么是三次握手,四次挥手
    
    # 2.为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
    这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
    
    # 3.为什么不能用两次握手进行连接?
    三次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
     现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。
    面试可能会遇到的问题(仅参考)

    (2)syn洪水攻击

    syn洪水攻击:syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。

    (3)半连接池

    半连接: 在三次握手过程中,服务端发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect),此时服务端处于SYN_RCVD状态

    半连接池(服务端)backlog:客户端每来一个请求,就会存放到半连接池。半连接池固定大小,只允许一定数量请求进入

    二、基于tcp协议的套接字socket

    tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端

    1、socket层

    2、什么是socket

    Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。Socket是封装好TCP/IP协议的接口。

    3、socket工作流程

    先从服务器端说起。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束

    from socket import socket, AF_INET, SOCK_STREAM
    
    IP = '127.0.0.1'
    PORT = 8888
    ADDRESS = (IP, PORT)
    BUFSIZE = 1024
    # 1.创建一个服务端对象(AF_INET:IPv4,SOCK_STREAM:sock流)
    ser_socket = socket(AF_INET, SOCK_STREAM)
    # 2.绑定服务器的IP地址,端口()
    ser_socket.bind(ADDRESS)
    # 3.设置半连接池,限制请求的个数
    ser_socket.listen(5)
    # 4.等待客户端请求
    cli_socket, cli_adrr = ser_socket.accept()
    print(cli_socket)
    print(cli_adrr)
    # 5.收发数据
    data = cli_socket.recv(BUFSIZE)
    print(data.decode('utf-8'))
    cli_socket.send('服务器已接收到数据'.encode('utf-8'))    # 只能以字节类型发送
    # 6.关闭与客户端的连接
    cli_socket.close()
    # 7.关闭服务器(一般不会关闭服务器)
    # ser_socket.close()
    TCP服务端
    from socket import socket, AF_INET, SOCK_STREAM
    
    IP = '127.0.0.1'
    PORT = 8888
    ADDRESS = (IP, PORT)
    BUFSIZE = 1024
    # 1.创建客户端socket对象
    cli_socket = socket(AF_INET, SOCK_STREAM)
    # 2.连接服务器
    cli_socket.connect(ADDRESS)
    # 3.发收数据
    cli_socket.send('hello'.encode('utf-8'))  # 只能以字节类型发送
    data = cli_socket.recv(BUFSIZE)
    print(data.decode('utf-8'))
    # 关闭客户端连接
    cli_socket.close()
    TCP客户端

    三、补充

    例如:https://www.cnblogs.com/linagcheng/p/9556260.html

    (1)https             :表示服务器协议

    (2)www.cnblogs.com             :表示域名,当访问服务器是,会通过DNS将域名解析为IP地址,然后通过IP地址访问服务器

    • 它有默认端口号:80             ======>www.cnblogs.com:80

    (3)/linagcheng/p/9556260.html               :表示服务器上的文件

  • 相关阅读:
    u-boot.lds分析
    u-boot的makefile中的一些目录的设定,以及涉及的shell,make语法。
    u-boot入门第一步,分析mkconfig
    uboot学习——Makefile里的echo使用!
    Linux下的打包与压缩和tar命令!
    关于undefined reference的问题
    JZ2440 编译Uboot1.1.6 undefined reference to ‘raise’
    POJ 1094 Sorting It All Out
    链式前向星
    Codeforces Round #197 (Div. 2) A~D
  • 原文地址:https://www.cnblogs.com/linagcheng/p/9556260.html
Copyright © 2020-2023  润新知