day033学习笔记

TCP协议

  • 定义及特性

    • 传输控制协议(使用情况多于udp)
    • 传输稳定:保证数据一定能收到
    • 相对UDP较慢
    • 在通信之前,必须先等待建立链接
  • TCP的三次握手及四次挥手

    • 三次握手

      • 第一次握手

        建立连接时,客户端向服务器发送请求同步包(SYN),并进入请求连接状态(SYN_SENT)等待服务器确认

      • 第二次握手

        服务器收到SYN包后回复客户端一个确认包(ACK,seq+1)+一个请求同步包(SYN),然后进入SYN派遣状态(SYN_RECV)等待客户端确认

      • 第三次握手

        客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(seq+1),然后客户端和服务器进入TCP连接成功状态(ESTABLISHED)

      • 理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去

    • 数据传输过程中

      如果有一方收到了对方的数据,一定会发送一个ACK确认包给发送方

    • 四次挥手

      • 第一次挥手

        主动关闭方调用close,会发送一个长度为0的数据包以及FIN(结束标志)

        用来关闭主动方到被动关闭方的数据传送,告诉被动关闭方:我已经不会再给你发数据了,但是,此时主动关闭方还可以接受数据

      • 第二次挥手

        被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1

      • 第三次挥手

        被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。

      • 第四次挥手

        主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手

  • TCP服务器

    • 长连接

      三次握手四次挥手之间分多次传递完所有数据(优酷看视频、在线游戏),长时间占用某个套接字

    • 短连接

      三次握手四次挥手之间传递少部分数据,多次握手挥手才传递完所有数据
      (浏览器),短时间占用

  • TCP服务器流程

    • socket创建一个套接字
    • bind绑定ip和port
    • listen设置最大等待连接数(收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求)
    • accept等待客户端的连接(接收连接请求)
    • recv/send收发数据
  • TCP单进程服务器

    from socket import *
    s = socket()
    addr = ("192.168.34.170",8989)
    s.bind(addr)
    s.listen(5)
    while True:
        print("主进程等待新客户端")
        client_s, client_addr = s.accept()
        print(f"主进程接下来负责处理,客户端ip:{client_addr[0]}客户端端口:{client_addr[1]}")
        try:
            while True:
                recdata = client_s.recv(1024)
                if len(recdata) > 0: #若收到数据为零,说明客户端已经调用close()
                    print(f"接收到客户端ip:{client_addr[0]}客户端端口:{client_addr[1]}信息:{recdata.decode()}")
                else:
                    print(f"客户端ip:{client_addr[0]}客户端端口:{client_addr[1]}已关闭")
                    break
        except ConnectionResetError:
            print("远程主机强迫关闭了一个现有的连接")
        except:
            print("其他未知错误")
        finally:
            client_s.close()
    
  • TCP多进程服务器

    from socket import *
    from multiprocessing import *
    from time import sleep
    def dealWithClient(client_s,client_addr):
        try:
            while True:
                recdata = client_s.recv(1024)
                if len(recdata) > 0:
                    print(f"接收到客户端ip:{client_addr[0]}客户端端口:{client_addr[1]}信息:{recdata.decode()}")
                else:
                    print()
                    print(f"客户端ip:{client_addr[0]}客户端端口:{client_addr[1]}已关闭")
                    break
        except ConnectionResetError:
            print("远程主机强迫关闭了一个现有的连接")
            return
        except:
            print("其他未知错误")
            return
        finally:
            client_s.close()
    
    def main():
        s = socket()
        s.setsockopt(SOL_SOCKET, SO_REUSEADDR,1)#貌似无必要
        addr = ("",7878)
        s.bind(addr)
        s.listen(5)
        try:
            while True:
                print("主进程等待新客户端")
                client_s, client_addr = s.accept()
                print("主进程创建新进程负责数据处理")
                client = Process(target=dealWithClient,args=(client_s,client_addr))
                client.start()
                client_s.close()#因为已经向⼦进程中copy了⼀份(引⽤),并且⽗进程中这个套接字也没有用处了,所以关闭(线程中不需要关闭)
        finally:
            s.close()
    
    if __name__ == '__main__':
        main()
    
  • 查询端口号是否被占用

    netstat -aon|findstr "xxxx"
    
posted @ 2019-10-24 08:35  寂静四月  阅读(112)  评论(0)    收藏  举报