Day6 PythonWeb全栈课程课堂内容

1. TCP协议介绍

  • TCP协议,传输控制协议,是一种面向连接的,双方必须先建立连接才能进行数据的传输、电话接通才可以传输数据,比udp可靠。

  • TCP特点:面向连接,可靠传输(TCP采用发送应答机制,超时重传,错误校验,流量控制和阻塞管理(网络出现阻塞))

  • TCP与UDP的区别

    • TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接。
    • TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。
    • UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
    • 每一条TCP连接只能是点到点的:UDP支持一对一,一对多和多对一和多对多的交互通信。
    • TCP对系统资源要求较多,UDP对系统资源要求较少。
  • UDP

在这里插入图片描述

  • TCP

在这里插入图片描述

2. TCP客户端

# 1.创建套接字
# 2.链接服务器
# 3.接收/发送数据
# 4.关闭套接字
# AF_INET是ipv4

# @Time : 2020/12/22 19:53
# @Author : Sam
# @File : TCP客户端.py
# @Software: PyCharm

'''
1.创建套接字
2.连接服务器
3.接收/发送数据
4.关闭套接字
'''

import socket

def main():
    # 创建套接字                     IPV4            字节流
    tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 连接服务器
    server_ip = input('Please server IP:')
    server_port = int(input("Please server PORT:"))
    server_addr = (server_ip, server_port)
    tcp_client.connect(server_addr)

    # 接收/发送数据
    send_data = input("send data:")
    tcp_client.send(send_data.encode('utf-8'))

    tcp_client.close()


if __name__ == '__main__':
    main()

在这里插入图片描述

  • 而在连接之后,网络助手断开就无法接收到数据了。

在这里插入图片描述

  • 接收数据
import socket

def main():
    # 创建套接字                     IPV4            字节流
    tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 连接服务器
    tcp_client.connect(('192.168.1.104', 8080))
    # 发送数据
    send_data = input("send data:")
    tcp_client.send(send_data.encode('utf-8'))
    # 接收数据
    recv_data = tcp_client.recv(1024)
    # print(recv_data) # b'******'
    print('接收到的数据:%s'%(recv_data.decode('utf-8')))
    tcp_client.close()
if __name__ == '__main__':
    main()

在这里插入图片描述

3. TCP服务端

TCP建立服务端步骤
• 1.socket创建套接字
• 2.bind绑定IP和port
• 3.listen使套接字变为可以被动链接
• 4.accept等待客户端的链接
• 5.recv/send接收发送数据
• 6.关闭套接字
  • 其中listen常定参数为128,

  • accept返回两个值,第一个返回套接字,第二个返回客户端地址。

    • 返回套接字得作用:功能监听套接字。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
type_ZmFuZ3poZW5naGVpdGk

'''
TCP服务端
• 1.socket创建套接字
• 2.bind绑定IP和port
• 3.listen使套接字变为可以被动链接
• 4.accept等待客户端的链接
• 5.recv/send接收发送数据
• 6.关闭套接字
'''

import socket


def main():
    # socket创建套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # bind绑定IP和port
    tcp_server.bind(('192.168.1.104', 7080))

    # listen使套接字变为可以被动链接,套接字创建出来是为了连接别人,而非别人连接你。
    tcp_server.listen(128)

    # accept等待客户端的链接,accept有两个返回值
    new_client_socket, client_addr = tcp_server.accept()
    '''
    print(new_client_socket) # 套接字
    print(client_addr) # 用户端地址
    '''
    
    # 接收数据
    recv_data = new_client_socket.recv(1024)
    print(recv_data.decode())
    
    # 发送数据
    new_client_socket.send('Hello'.encode('utf-8'))
    
    # 关闭套接字
    new_client_socket.close()
    tcp_server.close()
    
if __name__ == '__main__':
    main()

在这里插入图片描述

  • 优化,为客户端多次连接。
import socket


def main():
    tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    tcp_client.bind(('192.168.1.104', 8080))

    tcp_client.listen(128)

    new_client_socket, client_addr = tcp_client.accept()

    while True:
        recv_data = new_client_socket.recv(1024)

        if recv_data.decode('utf-8') == 'bye':
            break

        print(recv_data.decode('utf-8'))


    new_client_socket.close()
    tcp_client.close()


if __name__ == '__main__':
    main()

    

在这里插入图片描述

  • 为用户端创建可判断断开的条件

  • recv有个解堵塞
    在这里插入图片描述

  • 当我直接断开网络调试助手的连接时,会有一个返回值。

Traceback (most recent call last):
  File "D:/Python/venv/Python-web全栈开发课堂练习文件/Day5/tcp多次接收.py", line 30, in <module>
    main()
  File "D:/Python/venv/Python-web全栈开发课堂练习文件/Day5/tcp多次接收.py", line 19, in main
    recv_data = new_client_socket.recv(1024)
ConnectionAbortedError: [WinError 10053] 您的主机中的软件中止了一个已建立的连接。
import socket


def main():
    tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    tcp_client.bind(('192.168.1.104', 8080))

    tcp_client.listen(128)

    new_client_socket, client_addr = tcp_client.accept()

    while True:
        recv_data = new_client_socket.recv(1024)

        print(recv_data.decode('utf-8'))

        new_client_socket.send('Hello'.encode('utf-8'))

    new_client_socket.close()
    tcp_client.close()


if __name__ == '__main__':
    main()

  • 故解阻塞为1.收到数据。2.关闭客户端

    import socket
    
    
    def main():
        tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        tcp_client.bind(('192.168.1.104', 8080))
    
        tcp_client.listen(128)
    
        new_client_socket, client_addr = tcp_client.accept()
    
        while True:
            recv_data = new_client_socket.recv(1024)
    
            print(recv_data.decode('utf-8'))
            if recv_data:
                new_client_socket.send('Hello'.encode('utf-8'))
            else:
                break
    
        new_client_socket.close()
        tcp_client.close()
    
    
    if __name__ == '__main__':
        main()
    
    

在这里插入图片描述

  • 连接多个客户端来服务

    # @Time : 2020/12/22 22:59
    # @Author : Sam
    # @File : tcp服务多个客户端.py
    # @Software: PyCharm
    
    import socket
    
    
    def main():
        tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while True:
            print("Start.........")
            tcp_client.bind(('192.168.1.104', 8080))
    
            tcp_client.listen(128)
    
            new_client_socket, client_addr = tcp_client.accept()
    		print(client_addr)
            
            while True:
                recv_data = new_client_socket.recv(1024)
        
                print(recv_data.decode('utf-8'))
                if recv_data:
                    new_client_socket.send('Hello'.encode('utf-8'))
                else:
                    break
        
            new_client_socket.close()
        
        tcp_client.close()
    
    
    if __name__ == '__main__':
        main()
    

    在这里插入图片描述

  • 第一个发送完之后,断开,然后连接第二个。

4. send和recv原理剖析

  • socket的发送和接收缓冲区

    • 当创建一个TCP socket对象的时候会有一个发送缓冲区和一个接收缓冲区,这个发送和接收缓冲区指的就是内存中的一片空间。
  • send原理剖析

    • send是不是直接把数据发给服务端?
    • 不是,要想发数据,必须得通过网卡发送数据,应用程序是无法直接通过网卡发送数据的,它需要调用操作系统接口,也就是说,应用程序把发送的数据先写入到发送缓冲区(内存中的一片空间),再由操作系统控制网卡把发送缓冲区的数据发送给服务端网卡 。
  • recv原理剖析

    • recv是不是直接从客户端接收数据?
    • 不是,应用软件是无法直接通过网卡接收数据的,它需要调用操作系统接口,由操作系统通过网卡接收数据,把接收的数据写入到接收缓冲区(内存中的一片空间),应用程序再从接收缓存区获取客户端发送的数据。
  • send和recv原理剖析图

send和recv原理.png

5. 文件下载器

  • 基本逻辑

  • > 客户输入一个文件名字:demo.txt,将文件保存到本地
        1. 创建套接字
        2. 连接服务器
        3. 输入要下载的文件名称
        4. 发送文件下载请求
        5. 接收服务器发送过来的数据
        6. 保存数据,创建文件
        7. 关闭套接字
    > 服务端要返回文件的数据
        1. 创建套接字
        2. 绑定IP和Port
        3. listen主动变被动
        4. accept等待客户连接
        5. 接收文件名称/发送文件数据
        6. 关闭套接字
    
  • 接收客户端程序

  • '''
    > 客户输入一个文件名字:demo.txt,将文件保存到本地
        1. 创建套接字
        2. 连接服务器
        3. 输入要下载的文件名称
        4. 发送文件下载请求
        5. 接收服务器发送过来的数据
        6. 保存数据,创建文件
        7. 关闭套接字
    '''
    import socket
    
    
    def main():
        tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        server_IP = input('Server IP:')
        server_Port = int(input('Server Port:'))
        server_Addr = (server_IP, server_Port)
        tcp_client_socket.connect(server_Addr)
    
        file_name = input('File Name:')
        # 发送文件请求,发送文件名称
        tcp_client_socket.send(file_name.encode())
    
        # 就收服务器发送过来的数据
        recv_data = tcp_client_socket.recv(1024 * 1024)  # 1M
    
        if recv_data: # 为服务器断开提供判断条件。
            # 保存数据,创建新文件
            with open('[Get]' + file_name, 'wb') as new_file:
                new_file.write(recv_data)
    
        tcp_client_socket.close()
    
    if __name__ == '__main__':
        main()
    
  • 发送服务端程序

  • '''
    > 服务端要返回文件的数据
        1. 创建套接字
        2. 绑定IP和Port
        3. listen主动变被动
        4. accept等待客户连接
        5. 接收文件名称/发送文件数据
        6. 关闭套接字
    '''
    
    import socket
    
    
    def main():
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
        tcp_server_socket.bind(('192.168.1.104', 7070))
    
        tcp_server_socket.listen(128)
    
        new_client_socket, client_addr = tcp_server_socket.accept()
    
        file_name = new_client_socket.recv(1024).decode()
    
        file_content = ''
        try:
            with open(file_name, 'rb') as new_file:
                file_content = new_file.read()
        except Exception as e:
            print(e)
    
        new_client_socket.send(file_content.encode())
    
        new_client_socket.close()
    
        tcp_server_socket.close()
    
    if __name__ == '__main__':
        main()
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值