zoukankan      html  css  js  c++  java
  • TCP建立与断开连接、SOCKET通讯模板

    三次握手、四次挥手

    传输层中,TCP建立传输链接时的三次握手和关闭链接的四次挥手,因为socket工作于应用层和传输层之间,所以涉及建立链接和关闭链接的过程

    TCP使用窗口机制进行流量控制,什么是窗口?

    连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端;接收方发送的确认信息中包含了自己剩余的缓冲区尺寸;剩余缓冲区空间的数量叫做窗口

     

    LISTEN - 服务器侦听来自客户端TCP端口的连接请求; 
    SYN-SENT - 客户端在发送连接请求后等待匹配的连接请求; 
    SYN-RECEIVED -  服务器在收到和发送一个连接请求后等待对连接请求的确认; 
    ESTABLISHED- 代表一个打开的连接,数据可以传送给用户; 
    FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
    CLOSE-WAIT - 等待从本地用户发来的连接中断请求;

     

    FIN-WAIT-2 - 从远程TCP等待 连接中断请求; 
    LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认; 
    TIME-WAIT - 等待足够的时间以确保远程TCP接收到连接中断请求的确认; 
    CLOSED - 关闭,没有任何连接状态;

    三次握手:

    TCP/IP协议中,TCP协议采用三次握手建立一个连接。

    (1)第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。

    (2)第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。

    (3)第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。

    完成三次握手,客户端与服务器开始传送数据。

    确认号:其数值等于发送方的发送序号 +1(即接收方期望接收的下一个序列号)。

    四次挥手:

    TCP协议的连接是全双工连接,一个TCP连接存在双向的读写通道。TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。

    客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。

    详细过程:
        第一阶段   客户机发送完数据之后,向服务器发送一个FIN数据段,序列号为i;
        1.服务器收到FIN(i)后,返回确认段ACK,序列号为i+1,关闭服务器读通道;
        2.客户机收到ACK(i+1)后,关闭客户机写通道;
       (此时,客户机仍能通过读通道读取服务器的数据,服务器仍能通过写通道写数据)
        第二阶段 服务器发送完数据之后,向客户机发送一个FIN数据段,序列号为j;
        3.客户机收到FIN(j)后,返回确认段ACK,序列号为j+1,关闭客户机读通道;
        4.服务器收到ACK(j+1)后,关闭服务器写通道。
    这是标准的TCP关闭两个阶段,服务器和客户机都可以发起关闭,完全对称。
    FIN标识是通过发送最后一块数据时设置的,标准的例子中,服务器还在发送数据,所以要等到发送完的时候,设置FIN(此时可称为TCP连接处于半关闭状态,因为数据仍可从被动关闭一方向主动关闭方传送)。

    socket通讯模板

    import socket
    
    # 创建
    server = socket.socket()
    # 绑定
    server.bind(("192.168.12.154", 20000))
    # 监听
    server.listen()  # 指定半连接数 默认则由操作系统决定
    
    while True:
        #  接收,client:客户端的client对象 type为<class 'socket.socket'>,addr:客户端的("ip",端口号)
        client, addr = server.accept()
        while True:
            # 捕获异常  主要有 客户端强行关闭
            try:
                # 接收消息  可以理解为 双向通讯,在服务端有个client的同类负责和客户端里自己的同类交流 server请了个助手
                data = client.recv(1024)
                print(type(client), addr)
                if not data:  # 避免客户端正常close()后 没有send 但是服务端某种情况下不断执行data = client.recv(1024) 打印空data
                    client.close()
                    break
                print("来自客户端:", data.decode("utf8"))
                # 反馈消息
                client.send(input(">>>").encode("utf8"))
            except ConnectionResetError:
                print("客户端强行终止了通讯")
                client.close()
                break
    
    # while True在实际中是有条件终止的 终止后需要执行close()
    server.close()
    tcp 服务端
    import socket
    
    # 创建
    client = socket.socket()
    # 连接服务端
    client.connect(("192.168.12.154", 20000))
    
    while True:
        msg = input(">>>")
        # 发送
        client.send(msg.encode("utf8"))
        # 接收服务端回执的数据
        data = client.recv(1024)
        print("服务端:", data.decode("utf8"))
    
    # while True在实际中是有条件终止的 终止后需要执行close()
    client.close()
    tcp 客户端
  • 相关阅读:
    LightOJ 1341 Aladdin and the Flying Carpet 数学
    NOIP2013 花匠 DP 线段树优化
    LightOJ 1370 Bi-shoe and Phi-shoe 欧拉函数+线段树
    BZOJ2818: Gcd 欧拉函数求前缀和
    SPOJ3267 D-query 离线+树状数组 在线主席树
    BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca
    拓展欧几里得算法
    POJ1845Sumdiv(求所有因子和 + 唯一分解定理)
    UVA1635 Irrelevant Elements(唯一分解定理 + 组合数递推)
    codeforce 626E(二分)
  • 原文地址:https://www.cnblogs.com/dongzhihaoya/p/10172010.html
Copyright © 2011-2022 走看看