愚公移山日记·22

愚公移山日记·22

学习进度

今天的主要学习内容是TCP通信。
TCP是面向连接,可靠的基于字节流的传输控制协议,TCP有一下两个的特点:一是面向连接,二是可靠传送
可靠传输的原因有一下几点的原因:

  1. 应答机制
  2. 超时重传
  3. 错误校验
  4. 流量控制和阻塞管理

TCP和UDP的区别主要可以分为一下几点:

  • 面向连接(确认有创建第三方交流,连接已创建才传输)
  • 序数据传输
  • 重发丢失的数据包
  • 舍弃重复的数据包
  • 无差别的数据传送
  • 阻塞/流量控制
    对于TCP的建立一般按照一下几点步骤进行,
    在客户端:socket对象—>connect —>send(recv)—>close;
    服务器端:socket对象—>bind—>listen—>accept—>recv(send)—>close。
    服务端实现的具体步骤:
  • 导入模块,
  • 创建套接字,
  • 绑定端口,
  • 开启监听(把套接字由主动设置为被动),
    listen(128) 最大连接数目,等待客户端连接
    拆包, 使用新的套接字接受客户端发送的信息
    new_client_socket.recv(1024)
  • 关闭新的套接字
    new_client_socket.close()
  • 关闭服务器的套接字
    tcp_server_socket.closer()
    服务器不再接受新的客户,老客户端可以继续服务
实现TCP通信的的代码

TCP客户端

"""
导入模块
创建套接字 TCP
建立连接 connect()
发送数据
关闭套接字
"""
#导入模块
import  socket
#创建套接字 TCP
#socket.SOCK_STREAM TCP 传输方式
#socket.SOCK_DGRAM UPD 传输方式
tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#建立连接 connect()
#tcp_client_socket.connect(adress)
#adress 是一个元组,第一个表示的是字符串的IP地址,第二个表示的端口号
tcp_client_socket.connect(('',8080))
#发送数据
tcp_client_socket.send('字符串'.encode())
#接受信息
recv_data = tcp_client_socket.recv(1024)
#recv_data 保存的是客户端回复的信息的二进制
#解码
recv_text = recv_data.decode('gbk')
print('收到数据:',recv_text)
#关闭套接字
tcp_client_socket.close()

TCP通信的服务端

#导入模块
import socket
#创建套接字
tcp_server_socke = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#绑定端口和IP地址
tcp_server_socke.bind(('',8999))
#开启监听(设置套接字为被动模式)
#listen()作用设置 tcp_server_socke套接字为被动监听模式,不可以主动发送数据
#128 允许接受的最大的连接数目 ,windows 中是数据有效,而Linux中的数据无效
tcp_server_socke.listen(128)
#等待客户端连接
#accept() 开始接受客户端连接,程序会默认进入阻塞状态(等待客户端连接),如果客户端连接后程序自动接触阻塞
#recv_data 数据包含两不部分
#返回了一个新的套接字对象 socket
#客户端的IP地址和端口号 元组类型
while True :
    #这个循环是未让多个客户端同时进行,但是由于需要多线程。
    
    new_client_socket,client_ip_port = tcp_server_socke.accept()
    print('新客户端来啦:%s' %str(client_ip_port))
    #收发数据
    while True:
        #recv() 会让程序再次阻塞,收到信息之后再接着阻塞
        recv_data = new_client_socket.recv(1024)
        # 当接受到的数据为空的时候,表示客户端已经断开连接,服务端也要断开连接。
        if recv_data:
            recv_text = recv_data.decode('bgk')
            print('接收到[%s]的信息:%s' %(str(client_ip_port),recv_text))
        else:
            print('客户端已经断开连接')
            
            #new_client_socket() 表示不能再和当前的客户端通信
    new_client_socket.close()
#关闭连接
#tcp_server_socke.close()表示程序不再接受新的客户端连接,已经连接的可以继续服务
tcp_server_socke.close()

在后面还学习到了TCP通信的文件下载器
客户端

'''
导入模块
创建套接字
建立连接
接受用户输入的文件名
发送文件名到服务器
创建文件,并且准备保存
接受服务端发送到数据,保存到本地(循环)
关闭套接字
'''
#导入模块
import socket
#创建套接字
tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#建立连接
tcp_client_socket.connect(('IP地址',8080))
#接受用户输入的文件名
file_name = input('请输入要下载的文件名:\n')
#发送文件名到服务器
tcp_client_socket.send(file_name.encode())
#创建文件,并且准备保存
with open('下载的文件路径' + file_name,'wb') as file:
    while True:
        file_data = tcp_client_socket.recv(1024)
        if file_data:
            file.write(file_data)
        else:
            break
#关闭套接字
tcp_client_socket.close()

服务端

'''
导入模块
创建套接字
绑定端口
设置监听,设置套接字由主动为被动
接受客户端连接
接受客户端发送的文件名称
根据文件名读取文件的内容
把读取的内容发送给客户端(循环进行)
关闭当前的客户端的连接
关闭服务器
'''
#导入模块
import socket
#创建套接字
tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#设置套接字可以重用
#tcp_server_socket.setsockopt(当前套接字,属性名,属性值)
tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
#绑定端口
tcp_server_socket.bind(('IP地址',8080))
#设置监听,设置套接字由主动为被动
tcp_server_socket.listen(128)
#接受客户端连接
new_server_socket,ip_port = tcp_server_socket.accept()
print('欢迎新的客户端:',ip_port)
#接受客户端发送的文件名称
recv_data = new_server_socket.recv(1024)
file_name = recv_data.decode()
print(file_name)
#根据文件名读取文件的内容
with open(file_name,'rb') as file:
    #把读取的内容发生过客户端(循环)
    while True:
        file_data = file.read(1024)
        #判断是否读取了文件的末尾
        if file_data:
            #发送文件
            new_server_socket.send(file_data)
        else:
            break
   # 关闭和当前的客户端的连接
new_server_socket.close()
#关闭服务器
tcp_server_socket.close()

今天的分享就到这里啦

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页