• 网络传输--TCP


    TCP网络编程

    一、TCP简介

    二、TCP网络程序--客户端

    三、TCP网络程序--服务端

    四、TCP知识总结

    五、文件下载案例

    六、3次握手和4次挥手

    回到顶部

    一、TCP简介TCP

    1.TCP的简介

      TCP通信需要通过创建链接, 数据传送, 终止链接3个步骤

      

    2.TCP的特点

      面向连接: 建立间接, 通信, 关闭连接. 这种连接方式是一对一的, 所以不支持广播模式

      可靠传输

        应答机制: TCP发送的报文段必须都得到接受方的应答,才可以进行下步传输

        超时重传: TCP发送报文段的时候, 会启动定时器, 在规定时间内没有回应, 就进行重发

        错误校验: 由发送端计算,然后由接收端验证, 在此过程中出现差误的话, 则会直接丢弃这个包

        流量控制和阻碍管理: 根据实际情况来进行调整发送速度

      优缺点:

        优点: 可靠, 稳定传输数据

        缺点: 传输速度慢, 占用系统资源高, 不可以进行广播传输

      TCP和UDP的区别:

    TCP 面向连接; UDP 是不面向连接;

    TCP 提供可靠的数据传输,也就是说,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达; UDP 不保证可靠的数据传输,容易出现丢包情况;

    TCP 需要连接传输速度慢,UDP 不需要连接传输速度快

    TCP 不支持发广播; UDP 支持发广播

    TCP 对系统资源要求较多,UDP 对系统资源要求较少。

    TCP 适合发送大量数据,UDP 适合发送少量数据

    TCP 有流量控制,UDP 没有流量控制

    二、TCP网络程序--客户端

    ***注意***

    在使用windows的网络调试助手的过程中, 此软件传出的字节是GBK的编码, 但接收的过程中是Unicode的编码形式

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:Mr.yang
    import socket
    
    # 1.买个电话 -- 创建TCP套接字   参数是 地址协议版本 套接字类型
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2.拨号 创建和服务器的链接
    tcp_socket.connect(('192.168.33.68', 8080))
    
    # 3.发送数据
    choose = input(">>>:")
    tcp_socket.send(choose.encode())
    
    # 4.接受数据 阻塞等待数据 recv返回值一般情况下 就是对方发送的数据; 如果对方断开了链接 返回值就是 ''
    recv_data = tcp_socket.recv(1024)
    if not recv_data:
        print("对方断开链接")
    else:
        print(recv_data.decode('gbk'))
    
    # 5.关闭套接字
    tcp_socket.close()
    客户端

    三、TCP网络程序--服务端

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:Mr.yang
    import socket
    
    # 1.总机 - 创建TCP套接字<服务器套接字 监听套接字>
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 2.固定号码 - 固定端口
    server_socket.bind(('', 8888))
    
    # 3.安装客户服务系统 - 主动 -> 被动监听模式
    server_socket.listen(128)
    
    while True:
        # 4.从等待服务区取出一个客户端用以服务 转接到分机 - 接受链接
        # (<socket.socket 和客户端关联起来的套接字对象), raddr=('172.17.99.129', 53614)>, ('172.17.99.129', 53614))
        client_socket, client_addr = server_socket.accept()
        print("接受来自%s的数据请求" % str(client_socket))
    
        while True:
            # 5.使用分机进行深入的交流 - echo 回射服务器
            recv_data = client_socket.recv(1024)
            print("接受数据:%s" % recv_data.decode('gbk'))
            client_socket.send(recv_data.decode('gbk').encode())
            if not  recv_data:
                print("客户端下线了")
                break
    
        # 6.分机挂机
        client_socket.close()
    
    # 7.主机挂机
    server_socket.close()
    服务端

    四、TCP知识总结

    1.TCP 服务器一般情况下都需要绑定端口号,否则客户端找不到这个服务器
    2.TCP 客户端一般不绑定端口号,使用随机生成的端口号即可
    3.TCP 服务器中通过 listen 可以将 socket 创建出来的主动套接字变为被动的,这是做 TCP 服务器时必须要做的
    4.当 TCP 客户端和服务端建立好连接才可以收发数据,UDP 是不需要建立连接,直接就可以发送数据
    5.当一个 TCP 客户端和服务端连接成功后,服务器端会有1个新的套接字,这个套接字用来标记这个客户端,单独为这个客户端服务
    6.listen 后的套接字是被动套接字,用来接收新的客户端的链接请求的,而accept返回的新套接字是标记这个新客户端的
    7.关闭 listen 后的套接字意味着被动套接字关闭了,会导致新的客户端不能够链接服务器,但是之前已经链接成功的客户端正常通信。
    8.关闭 accept 返回的套接字意味着这个客户端已经服务完毕
    9.当客户端的套接字调用 close 后,服务器端会 recv 解堵塞,并且返回的长度为0,因此服务器可以通过返回数据的长度来区别客户端是否已经下线

    五、文件下载案例

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:Mr.yang
    import socket
    
    # 1.建立和服务器的连接
    # 1.1 用户输入IP地址和端口
    IP = input("服务器IP:")
    port = int(input("服务器端口:"))
    
    # 1.2 创建TCP套接字
    tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    # 1.3 连接服务器
    tcp_socket.connect((IP, port))
    
    # 2.向服务器发送需要下载文件的名称
    # 2.1 输入文件名称
    file_name = input('需要下载的文件名称:')
    
    # 2.2 发送
    tcp_socket.send(file_name.encode())
    
    # 3.一遍接收文件数据 一遍写入数据
    # 3.1 打开文件用于保存 接收到的数据
    file = open("下载" + file_name, "wb")
    while True:
        # 3.2 接收数据 写入文件
        file_data = tcp_socket.recv(4096)
    
        # 3.3 如果数据是'' 传输完成 关闭文件 套接字  否则继续3.2的步骤
        if not file_data:
            print("文件下载完成")
            file.close()
            tcp_socket.close()
            break
        file.write(file_data)
    客户端
    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    # Author:Mr.yang
    import socket
    
    def main():
    
        # 1.创建和客户端的连接
        # 1.1 创建套接字
        tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        tcp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    
        # 1.2 绑定端口
        tcp_socket.bind(('192.168.33.68', 8888))
    
        # 1.3 监听
        tcp_socket.listen(128)
    
        # 1.4 接收连接
    
        while True:
            clent_socket, clent_addr = tcp_socket.accept()
            print("接收来自%s的连接" %  str(clent_socket))
    
            # 2.接收客户端发送的文件名
            # 2.1 使用和客户关联的套接字对象 接收数据
            file_name = clent_socket.recv(4096)
            if not file_name:
                print("客户端已经断开链接")
                clent_socket.close()
                continue
            # 2.2 文件名称解码成 str
            new_file_name = file_name.decode()
    
            # 3.根据文件名称 读取文件数据 发送给客户端
            # 3.1 打开文件
            with open(new_file_name, "rb") as file:
                # 3.2读取整个文件的数据
                data = file.read() # 如果文件大 可能导致程序出现风险
    
                # 3.3 向客户端发送数据
                clent_socket.send(data)
    
        tcp_socket.close()
    
    if __name__ == '__main__':
        main()
    服务端

    六、3次握手和4次挥手

    3次握手

                  

        标志位:

          SYN: 表示连接请求  ACK: 表示确认  FIN: 表示关闭连接  seq:表示报文序号  ack: 表示确认序号

    第一次握手:
        Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
    
    第二次握手:
        Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack (number )=J+1,随机产生一个值seq=K,
    并将该数据包发送给 Client以确认连接请求,Server进入SYN_RCVD状态。 第三次握手: Client收到确认后,检查ack是否为J
    +1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,
    如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

    4次挥手

    第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送。
    
    第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1。
    
    第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送。
    
    第四次挥手:Client收到FIN后,接着发送一个ACK给Server,确认序号为收到序号+1。
  • 相关阅读:
    Jmeter
    http请求的全过程
    前端知识
    jmeter连接MySQL数据库、sqlserver数据库
    jmeter 生成随机字符串、获取当前时间
    jmeter跨线程组传参
    fiddler抓不到iis网站包的问题
    jmeter登录数据库-- 通过windows身份验证方法(DNS)
    ant安装(Windows系统)
    tomcat安装(Windows系统)
  • 原文地址:https://www.cnblogs.com/Mryang123/p/9979250.html
Copyright © 2020-2023  润新知