精华内容
下载资源
问答
  • 封面图片来源:沙沙野内容概览三次握手四次挥手...就是因为它有三次握手四次挥手过程先建立连接,进行三次握手:就好比 QQ 客户端 给服务器发送一个值 1200,问它,"能收到我的消息吗"这时服务器回答,"可以...

    28e2ba01a58d05c0807fbb7cca0080f4.png
    封面图片来源:沙沙野

    内容概览

    1. 三次握手与四次挥手
    2. TCP 协议与 UDP 协议的流程图
    3. socket 层
    4. socket 基本运用
    5. 传输中文时的方法
    6. 带退出的聊天程序
    7. 小练习
    8. 服务端同时接收多个客户端消息

    三次握手与四次挥手

    1. TCP 协议之所以传输稳定、可靠,就是因为它有三次握手和四次挥手的过程
    2. 先建立连接,进行三次握手:
    • 就好比 QQ 客户端 给服务器发送一个值 1200,问它,"能收到我的消息吗"
    • 这时服务器回答,"可以",并且返回给 QQ 客户端一个值 1201 来表示接收到了。然后服务器要问 QQ 客户端,"能收到我的消息吗"
    • QQ 客户端回复,"可以"
    • 这就是建立连接的三次握手。注意,服务器发送 1201 和问 QQ 客户端归于一次握手

    3. 数据传输的过程

    • QQ 客户端给服务器发送一条消息
    • 服务器收到后给 QQ 客户端返回一条消息
    • 这两个过程合在一起才算一个完整的数据传输

    4. 断线连接四次挥手

    • QQ 客户端给服务器发送一条消息,"我要结束通话了"
    • 服务器接收到后,回复一条消息,"收到了"
    • 服务器又回复,"我也结束通话了"
    • QQ 客户端回复,"好的"

    TCP 协议与 UDP 协议的流程图

    9eb4125a01cecda6150e592c102e091f.png

    socket 层

    1. 所处位置:在应用层和下面所有层之间的位置
    2. 有了 socket 可以以相对简单的方式进行网络通信
    3. 本质上是帮助我们解决两个程序之间通信
    4. socket 是应用层与 TCP/IP 协议通信的中间软件抽象层,是一组接口

    60dce6f8fa18d485ee22b68481c95db3.png

    socket 基本运用

    1. 下面开始举例加深对 socket 的理解。首先,新建一个文件,命名为 "server.py",在同一目录下再建一个文件,命名为 "client.py"
    2. TCP 是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端
    3. server.py 中的内容
    # 导入套接字的包
    import socket
    
    sk = socket.socket()
    # 把地址绑定到套接字
    sk.bind(("127.0.0.1", 8080))
    # 注意:元组的第一个元素是字符串形式的 IP 地址,必须是本电脑的
    # IP 地址有两种
    #   a. 192.168.13.4, 在cmd里面输入 ipconfig 即可查询
    #   b. 127.0.0.1, 本地回环地址
    
    # 这两个ip地址的作用是不一样的
    #   a. 192.168.... 表示所有的和我在同一个局域网的小伙伴都能访问
    #   b. 127.0.0.1   则只有在自己电脑的 client 才能用
    
    # 元组内的第二个元素是端口号,一般在8000-10000之间
    
    
    # 三次握手
    # 监听链接
    sk.listen()
    # 阻塞,直到有一个客户端来连接
    conn, addr = sk.accept()  
    print(addr)
    
    # 注意发送的内容必须是 bytes 类型
    conn.send(b"Hi, can you receive my message?")
    # 最多接收1024个字节,没1024时有多少接收多少
    msg = conn.recv(1024)
    print(msg)
    
    # 四次挥手
    # 关闭客户端套接字
    conn.close()
    # 关闭服务器套接字
    sk.close()

    4. client.py 中的内容

    import socket
    
    # 创建客户端套接字
    sk = socket.socket()
    # 把三次握手建立起来了,尝试连接服务器
    # 这里 connect 一次,上面(server.py)就 accept 一次
    sk.connect(("127.0.0.1", 8080))
    
    # 对话(发送/接收)
    msg = sk.recv(1024)
    print(msg)
    
    sk.send(b"Yep, How are you?")
    # 关闭客户端套接字
    sk.close()
    
    # 然后先运行 server.py, 再运行 client.py,两个都会有结果
    # 注意收发次数要相等,还要一一对应

    5. 先运行 server.py,再运行 client.py,两个都会有结果

    # server.py 运行后,会先把消息发给客户端,并处于等待状态
    # 待客户端接收到并反馈后,才有以下结果:
    ('127.0.0.1', 42060)
    b'Yep, How are you?'
    
    # client.py 运行后,马上接收到了服务端发来的消息,然后反馈回去
    # 运行结果:
    b'Hi, can you receive my message?'

    传输中文时的方法

    1. 无论是服务端还是客户端,发送中文信息前先对消息进行编码;接收中文信息后,对消息进行解码
    2. server.py 中的内容示例
    import socket
    
    sk = socket.socket()
    sk.bind(("127.0.0.1", 8080))
    
    sk.listen()
    conn, addr = sk.accept()
    
    # 发送消息前,对其编码
    conn.send("你好,能接收到我的消息吗?".encode())
    
    recv_msg = conn.recv(1024)
    # 接收消息后,对其解码
    decode_recv_msg = recv_msg.decode("utf-8")
    print(decode_recv_msg)
    
    conn.close()
    sk.close()

    3. client.py 中的内容示例

    import socket
    
    sk = socket.socket()
    sk.connect(("127.0.0.1", 8080))
    
    msg = sk.recv(1024)
    # 接收消息后,对其解码
    decode_msg = msg.decode()
    print(decode_msg)
    
    # 发送消息前,对其编码
    sk.send("你好,可以接收到你发的消息".encode())
    
    sk.close()

    4. 先运行 server.py,再运行 client.py,运行结果如下

    # server.py
    你好,可以接收到你发的消息
    
    # client.py
    你好,能接收到我的消息吗?

    带退出的聊天程序

    1. 上面的示例中服务端与客户端只是建立一次链接,实际运用中肯定不是连一次对话一次,因此,可以写一个程序,能够让双方都保持通信状态,并且可以随时结束聊天
    2. server.py 中的内容
    import socket
    
    sk = socket.socket()
    sk.bind(("127.0.0.1", 8800))
    
    sk.listen()
    conn, addr = sk.accept()
    # 注意在 accept 之后加上循环
    # 是为了能够让我们和一个客户端多说几句话
    while 1:
        send_msg = input("msg: ")     
        conn.send(send_msg.encode())
        # 设置结束聊天的条件
        if send_msg == "q": break
    
        msg = conn.recv(1024).decode()
        if msg == "q": break
        print(msg)
    
    conn.close()
    sk.close()

    3. client.py 中的内容

    import socket
    
    sk = socket.socket()
    sk.connect(("127.0.0.1", 8800))
    while 1:
        msg = sk.recv(1024).decode()
        if msg == "q": break
        print(msg)
    
        send_msg = input("msg: ")
        sk.send(send_msg.encode())
        if msg == "q": break
    
    sk.close()

    4. 先运行 server.py,再运行 client.py,双方可以一直保持通信状态,当有一方输入 q 之后,相互之间的通信结束

    # 注意:如果运行 server.py 时报错:
    Traceback (most recent call last):
      File "server.py", line 4, in <module>
        sk.bind(("127.0.0.1", 8800))
    OSError: [Errno 98] Address already in use
    
    # 解决办法:把两个文件中的端口号改一下即可,比如把 8800 改为 8000 再依次重新运行
    
    
    # 带有 msg: 的表示发送的消息,不带的就是接收到的消息
    # server.py
    msg: 你好  
    下午好
    msg: 很高兴和你聊天
    我也是
    msg: 再见
    再见
    msg:  q
    
    # client.py
    你好
    msg: 下午好
    很高兴和你聊天
    msg: 我也是  
    再见
    msg: 再见

    小练习

    1. 问题描述:所有的 client 端都要以 server 端的时间为基准,client 端发送一个时间格式——"%Y-%m-%d %H:%M:%S",server 端根据接收到的时间格式向客户端返回时间
    2. 大概思路解析:按照上面的题意,应该是先客户端向服务端发送消息,服务端接收到后再进行处理,而不是像上面的示例一样,先服务端发送消息
    3. server.py 中的内容
    import socket
    import time
    
    sk = socket.socket()
    sk.bind(("127.0.0.1", 9000))
    sk.listen()
    
    conn, addr = sk.accept()
    
    msg = conn.recv(1024)
    print("接收到客户端传来的消息:%s" % msg)
    
    format_msg = time.strftime(msg.decode())
    conn.send(format_msg.encode())
    
    conn.close()
    sk.close()

    4. client.py 中的内容

    import socket
    
    sk = socket.socket()
    sk.connect(("127.0.0.1", 9000))
    
    sk.send(b"%Y-%m-%d %H:%M:%S")
    
    msg = sk.recv(1024).decode()
    print("接收到服务端传来的消息:%s" % msg)
    
    sk.close()

    5. 同样先运行 server.py,再运行 client.py

    # server.py
    接收到客户端传来的消息:b'%Y-%m-%d %H:%M:%S'
    
    # client.py
    接收到服务端传来的消息:2019-11-25 17:37:52

    服务端同时接收多个客户端消息

    1. server.py 中的内容
    import socket
    import time
    
    sk = socket.socket()
    sk.bind(("127.0.0.1", 8000))
    sk.listen()
    
    # 在 accept 之前加上循环,能够让我们和多个客户端进行沟通
    # 注意与上面『带退出的聊天程序』中的循环的区别
    while 1:
        # 接收一个客户端的请求
        conn, addr = sk.accept()
        print(addr)
    
        msg = conn.recv(1024)
        print("接收到客户端传来的消息:%s" % msg)
    
        format_msg = time.strftime(msg.decode())
        conn.send(format_msg.encode())
        # 断开一个客户端的请求
        conn.close()
    
    sk.close()

    2. client.py 中的内容

    import socket
    
    sk = socket.socket()
    sk.connect(("127.0.0.1", 8000))
    
    sk.send(b"%Y-%m-%d %H:%M:%S")
    
    msg = sk.recv(1024).decode()
    print("接收到服务端传来的消息:%s" % msg)
    
    sk.close()

    3. 先运行 server.py,再重复运行 client.py,发现 server.py 的运行结果会不断刷新,不会报错

    # server.py:
    (base) yanfa@yanfa-H110SD3-C:~/Desktop$ python server.py 
    ('127.0.0.1', 46500)
    接收到客户端传来的消息:b'%Y-%m-%d %H:%M:%S'
    ('127.0.0.1', 46502)
    接收到客户端传来的消息:b'%Y-%m-%d %H:%M:%S'
    ('127.0.0.1', 46504)
    接收到客户端传来的消息:b'%Y-%m-%d %H:%M:%S'
    ('127.0.0.1', 46506)
    接收到客户端传来的消息:b'%Y-%m-%d %H:%M:%S'
    ('127.0.0.1', 46508)
    接收到客户端传来的消息:b'%Y-%m-%d %H:%M:%S'
    
    
    # client.py:
    (base) yanfa@yanfa-H110SD3-C:~/Desktop$ python client.py 
    接收到服务端传来的消息:2019-11-25 18:05:58
    
    (base) yanfa@yanfa-H110SD3-C:~/Desktop$ python client.py 
    接收到服务端传来的消息:2019-11-25 18:06:00
    
    (base) yanfa@yanfa-H110SD3-C:~/Desktop$ python client.py 
    接收到服务端传来的消息:2019-11-25 18:06:01
    
    (base) yanfa@yanfa-H110SD3-C:~/Desktop$ python client.py 
    接收到服务端传来的消息:2019-11-25 18:06:02
    
    (base) yanfa@yanfa-H110SD3-C:~/Desktop$ python client.py 
    接收到服务端传来的消息:2019-11-25 18:06:03
    展开全文
  • TCP的三次挥手四次握手 TCP之所以要用三次握手,主要为了完成如下几个目标 1)防止旧的SYN生效,比如 原来发出的SYN ,由于网络环境比较差,一直没有发送到服务端,客户端又发出了新的SYN, 这时候,如果旧的...

    TCP的三次挥手和四次握手

    TCP之所以要用三次握手,主要为了完成如下几个目标

    1)防止旧的SYN生效,比如 原来发出的SYN ,由于网络环境比较差,一直没有发送到服务端,客户端又发出了新的SYN,

          这时候,如果旧的SYN ACK已经返回,那么,client就要回复一个RST给到服务器端,因为新SYN已经发出了,如果没有

          三次握手,那么就可能造成多次连接的存在

    2)同步双方的序列号

    四次挥手:

     四次挥手的过程:

     首先 主动断开的一方,发送FIN 报文,进入FIN_WAIT1 状态,被动的一方收到以后,发送 ACK报文,进入CLOSED_WAITED状态,

     主动断开的一方收到ACK报文以后,进入FIN_WAIT2状态。CLOSED_WAIT的作用是代表被断开端继续发送没有发送完成的数据。处理

    完成以后,继续发送FIN包,主动方收到以后发送ACK,进入TIME_WAIT状态,而被动方进入LAST_ACK状态,在收到最后一个ACK以后,被动方

    关闭,但是主动方的TIME_WAIT会继续一段时间。

    TIME_WAI的时长是2MSL,也就是报文的最大生存时间的2倍,也就是60s。

     

    为什么需要TIME_WAIT状态:

    1)防止收到旧的报文 

    假如 被动方发送的一个SEQ = 301的报文,但是这个报文因为网络原因延迟,这个时候,如果发生了断开连接又重连的情况,新连接就有可能收到这个旧的数据包。

    2)保证连接正常关闭

    如果最后一个ACK失效,那么,被动方就会发新的FIN报文,这样一来一回正好2MSL,如果没有这个等待或者过短,那么如果ACK丢了,就会出现被动方无法关闭的情况

    大量CLOSE_TIME产生的原因:

    大量的close wait 产生的原因是因为客户端异常断开造成的,CLOSE_WAIT大量存在会占用过多的fd导致新的连接没法连接,

    解决办法,如果客户端异常断开,需要在epoll里面监听 EPOLLRDHUP这个事件,在收到事件以后,就colse掉这个fd。

     

    展开全文
  • TCP三次握手四次挥手过程 原文链接

    TCP三次握手四次挥手过程

    原文链接

    展开全文
  • 倘若利用TCP协议,则传输前有三次握手,传输后有三次挥手,是一个可靠传输。 倘若利用UDP协议,传输前不需要建立连接,对方收到后也不需要发送确认,是一个不可靠的传输,但是胜在消耗资源少,速度快。 2.三次握手 ...

    1.前言

    网络通信的实体是不同主机之间进程的通信,也就是端到端通信,其过程借助于TCP或者UDP协议,基于端口。
    倘若利用TCP协议,则传输前有三次握手,传输后有三次挥手,是一个可靠传输。
    倘若利用UDP协议,传输前不需要建立连接,对方收到后也不需要发送确认,是一个不可靠的传输,但是胜在消耗资源少,速度快。

    2.三次握手

    首先我们需要知道为什么要三次握手而不是两次。原因是为了防止之前传输过的请求连接的数据包延时到达服务器后,服务器再次创建新的连接而导致的错误。
    如果我们只使用二次握手,假设有这么一种情况,我们先发了一个syn包,这个包因为某种原因被阻塞到网络中,这时候我们又发送了一个syn包,这次收到了对方的ack+syn包,tcp连接已经建立。过了一会儿之前阻塞的syn包发送到了对方主机,对方主机又返回了一个ack+syn包,这时候又建立了一个tcp连接。但我们是只想建立一个tcp连接的,这时候出现了两个,浪费了资源。为了解决这种情况,因此就出现了tcp三次握手。
    假设我们使用tcp三次握手,就可以避免这个情况,因为即使之前被阻塞的包被发送到了服务端,服务端返回了ack+syn包,但只要我们不发送最后的第三次握手也就是ack包,就不会建立连接,也就不会有资源的浪费,这就是tcp连接为什么是三次的原因。
    在这里插入图片描述

    3.四次挥手

    在这里插入图片描述

    通过四次挥手来结束tcp连接,也是有其原因的,我的理解是这个样子的:

    1. 第一次客户端发送fin包,告诉服务端,我不会再给你传送数据了并且我想要断开连接。
    2. 第二次服务端发送ack包,告诉客户端,这是我这边剩余要发送的数据,等发送完在关。
    3. 第三次服务端发送fin+ack包,告诉客户端,我这边发送结束,可以中断连接了。
    4. 第四次客户端发送ack包,告诉服务端,好的。

    4.参考文章

    两张动图-彻底明白TCP的三次握手与四次挥手

    展开全文
  • 三次握手四次挥手过程 三次握手 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。 第一次握手:建立连接时,客户端发送syn 包(tcp 协议中syn位置1,序号为J)到服务器,并进入SYN_ ...
  • 文章目录TCP次握手和四次挥手过程1、次握手(1)次握手的详述(2)总结三次握手过程:(3)为什么A还要发送一次确认呢?可以二次握手吗?(4)Server端易受到SYN攻击?2、四次挥手(1)四次挥手的详述(2)...
  • 一、标识符 seq:"sequance"序列号;ack:"acknowledge"确认号;SYN:"synchronize"请求同步...、关闭TCP连接,四次挥手 客户端:我说完了,我要闭嘴了; 服务端:我收到请求,我要闭耳朵了; (客户端收到这个确认,
  • 1、三次握手(1)三次握手的详述首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。 最初两...
  • 三次握手 四次挥手
  • 封面图片来源:沙沙野内容概览三次握手四次挥手...就是因为它有三次握手四次挥手过程先建立连接,进行三次握手:就好比 QQ 客户端 给服务器发送一个值 1200,问它,"能收到我的消息吗"这时服务器回答,"可以...
  • HTTP三次握手四次挥手过程HTTP三次握手四次挥手过程基本描述工作流程建立连接-TCP三次握手为什么三次握手断开连接-TCP四次挥手为什么四次挥手 HTTP三次握手四次挥手过程 基本描述 http协议全称:HyperText Transfer...
  • 为什么连接的时候是次握手,关闭的时候却是四次握手? 答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server...
  • 下面,我们用情侣从表白到分手的过程来类比说明,什么是TCP的三次握手四次挥手。建立连接之三次握手我们来看看情侣在谈恋爱之前,他们是如何确立关系的?其实计算机之间通过TCP三次握手来建立连接,跟上面情侣建立...
  • 目录三次握手术语解释过程描述图解四次挥手过程描述图解 三次握手 术语解释 syn包:TCP连接的第一个包,非常小的一种数据包 ACK:ACK (Acknowledge character)即是确认字符,在数据通信中,接收站发给发送站的一种...
  • 描述TCP三次握手四次挥手过程的图片
  • 1、三次握手(1)三次握手的详述首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。 最初两...
  • 三次握手: 假设 A 为客户端,B 为服务器端。 首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。(A:CLOSED B:LISTEN) A 向 B 发送连接请求报文,SYN=1,ACK=0,选择一个初始的序号 x。(A:SYN_SEND B:...
  • 简述TCP三次握手四次挥手过程
  • 三次握手–连接在通信的过程中,Client与Server建立TCP连接需要三次握手,为什么需要三次握手呢?又是怎么握手的过程?TCP连接是可靠的通信方式,必须要保证两端都同时有效,且线路通畅。如同两个人通话,但并不确定...
  • HTTP三次握手四次挥手过程

    千次阅读 2018-08-27 14:14:43
    一、HTTP协议三次握手过程 1.1名词解释。   SYN(Synchronous 位码,表示建立联机)   Seq(Sequence number 顺序号码)   ACK(Acknowledgement 确认值)   Ack(Acknowledgement number 确认号码) ...
  • 三次握手过程四次挥手过程
  • 次握手与四次挥手过程详解次握手建立连接:传输数据过程:四次握手断开连接:常见面试问题: TCP通信过程包括个步骤:建立TCP连接通道,传输数据,断开TCP连接通道 上图主要包括部分:建立连接、传输数据、...
  • 点击上方“不太厉害的程序猿”,选择“置顶或者星标”你关注的... 三次握手2. 四次挥手3. TCP是如何保证可靠性的 TCP在网络协议中是非常重要的,要说有多重要的话,那就像珍珠奶茶的奶茶一样。1. 三次握手TCP在进...
  • 简述TCP的三次握手四次挥手过程

    万次阅读 多人点赞 2018-05-11 10:28:40
    ①TCP是一种精致的,可靠的字节流协议。 ②在TCP编程中,路握手一般由客户端(Client)调用Connent函数...④简述握手过程: 图 .TCP三次握手 (1)第一次握手:Client将标志位SYN置为1,随机产生一个值s...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,989
精华内容 1,595
关键字:

三次挥手四次握手过程