在传输层,有一个重点是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连接处于半关闭状态,因为数据仍可从被动关闭一方向主动关闭方传送)。

(引用:https://www.cnblogs.com/Jessy/p/3535612.html)

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 客户端

TCP建立与断开连接、socket通讯模板的更多相关文章

  1. 深入理解TCP建立和关闭连接

    建立连接: 理解:窗口和滑动窗口TCP的流量控制TCP使用窗口机制进行流量控制什么是窗口?连接建立时,各端分配一块缓冲区用来存储接收的数据,并将缓冲区的尺寸发送给另一端 接收方发送的确认信息中包含了自 ...

  2. tcp 服务端如何判断客户端断开连接

    一篇文章:   最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与server端建立连接,然后发送消息给server.我在server端会使用专门的线程处理一条socket连接 ...

  3. 【VS开发】TCP服务端如何判断客户端断开连接

    原文出自:http://www.cnblogs.com/youxin/p/4056041.html 一篇文章:   最近在做一个服务器端程序,C/S结构.功能方面比较简单就是client端与serve ...

  4. TCP建立连接和断开连接图解

    参考博客: http://blog.csdn.net/whuslei/article/details/6667471 http://www.2cto.com/net/201310/251896.htm ...

  5. TCP建立连接的三次握手和TCP连接断开的四次挥手

    1. TCP建立连接的3次握手 2. TCP断开连接的四次挥手 [注意]中断连接端可以是Client端,也可以是Server端. 图3—Client端主动发起关闭连接请求 1. 假设Client端主动 ...

  6. Linux Socket过程详细解释(包括三次握手建立连接,四次握手断开连接)

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web 服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠s ...

  7. TCP建立连接和断开连接过程

    假设Client端发起中断连接请求,也就是发送FIN报文.Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着 ...

  8. TCP面试题之为什么需要三次握手才能建立连接/四次挥手才能断开连接

    为什么需要三次握手才能建立连接? 答:为了初始化Sequence Number(序列号)的初始值,要通知双方数据包的序号,作为以后通讯的序号,以保证在网络传输过程,不会因为网络原因而导致乱序: 为什么 ...

  9. TCP连接的建立和断开

    1.TCP连接的建立            设主机B运行一个服务器进程,它先发出一个被动打开命令,告诉它的TCP要准备接收客户进程的连续请求,然后服务进程就处于听的状态.不断检测是否有客户进程发起连续 ...

随机推荐

  1. String.split()方法

    如果用“(”作为分隔的话,必须是如下写法,String.split("\\("),这样才能正确的分隔开,不能用String.split("("); 如果用“)” ...

  2. 解决wso2 axis2server 跑不起

    wso2ei-6.1.0 运行axis2server报下面找个错误 Server could not start due to class loading issue java.lang.NoSuch ...

  3. cocos-lua3.17 Lua tablrView工具类

    local MyTableView = class("MyTableView") MyTableView.__index = MyTableView MyTableView.pro ...

  4. jmeter保持登录

    1.添加配置元祖---http cookie 管理器(注意上面的http cookie管理器和其他的配置是对其的) 2.这里是当你想要配置多用户并发是要配置不同的账号,配置后记得上面的第一张图的清除c ...

  5. python练习:实现一个整数数组里面两个数之和为183的所有整数对

    l1 = [183,0,1,2,-184,367] num = [] for i in range (0,len(l1)): for l in range (i+1,len(l1)): if l1[i ...

  6. java基础继承

    为什么用继承: 因为继承可以减少代码的冗余,提高维护性,为了从根本上解决存在的问题,就需要继承,就是将多个类当中的相同的地方提取到一个父类当中.父类更通用,子类更具体. 父类的继承格式 语法:publ ...

  7. C#获取本地磁盘信息【转载】

      直接上干货简单易懂 //磁盘监控(远程/本地)//需要引用System.Management.dllpublic class RemoteMonitoring{private static str ...

  8. [转载] Fiddler为所欲为第三篇 封包逆向必备知识[三]

    导语: 小A同学:会抓包有什么好学习的,不就用一个工具设置个wifi代{过}{滤}理就OK了嘛,还不是很多做不了.不如学习安卓逆向.didi科学家:不好意思,抓包可以为所欲为. 其实学习抓包,完完全全 ...

  9. linux下jvm优化、tomcat调优

    系统环境:jdk1.8,apache-tomcat-8.5.35 一.jvm优化 进入 bin/catalina.sh,修改JAVA_OPTS配置: JAVA_OPTS="-server - ...

  10. 神州数码BGP路由协议配置

    实验要求:了解BGP路由协议的配置方法及原理 拓扑如下 R1 enable 进入特权模式 config 进入全局模式 hostname R1 修改名称 interface l0 进入端口 ip add ...