Socket编程

Socket编程

对于Python而言,进行Socket编程,发送网络消息,可以使用Python内置的Socket库;目前使用最多的是利用TCP协议来进行网络通行的

利用TCP进行通信的双方,称之为服务端(severt)与客户端(client),TCP协议双方通信之前需要建立连接,然后才能进行信息的传递(三次握手)

编码流程:
"""服务器端:
		1.实例化创建Socket对象
		2.绑定本地IP地址与端口号
		3.监听
		4.模拟三次握手建立连接过程,返回通信Socket对象
		5.进行信息的接受与发送
		6.关闭连接"""

"""客户端端:
		1.实例化创建Socket对象
		2.与服务端建立连接(需要预先知道服务器端的IP地址与端口号)
		3.进行信息的发送与接受
		4.关闭连接"""
传送消息的格式为字符串
服务器端代码:
#服务端

#导入socket库
from socket import *
#定义配置参数
#本地IP地址
IP="0.0.0.0"
#本地端口号
PORT=50000
#定义一次性从SOCKET缓冲区中读取最大字节数
BUFFERMAX=512

#创建Socket对象
"""参数说明:
    参数AF_INET表明该对象网络层使用IP协议
    参数SOCK_STREAM表明该对象传输层使用TCP协议"""
listenSocket=socket(AF_INET,SOCK_STREAM)
#给当前SOCKET绑定地址和端口号
listenSocket.bind((IP,PORT))

#使socket进程处于监听状态,等待客户端的连接请求
#参数表明最多可以接受等待连接的客户端数目,如4表明当前最多可以接受4个客户端的请求
listenSocket.listen(4)
print("服务端启动成功,在端口号{PORT}等待客户端的连接")

"""返回参数说明:
    dataSocket:新的Socket对象,用于信息传递
    addr:以元组的形式返回客户端的(IP地址,端口号)
"""
dataSocket,addr=listenSocket.accept()  #建立连接,三次握手过程
print("接受一个客户端连接",addr)


while True:
    #读取客户端发送的信息
    #参数说明:BUFFERMAX 指定从接受缓冲区中读取的最大字节数
    recved=dataSocket.recv(BUFFERMAX)   #一直等待对方信息,当对方关闭连接时,返回的是一个空的字节

    #返回数据recved为空Byte,表明对方关闭连接,退出当前循环
    if not recved:
        break

    #读取的数据为Bytes类型,需要解码为字符串类型
    info=recved.decode()
    print(f"接收到的信息为:{info}")

    #发送的数据必须要为Bytes类型,需要编码
    dataSocket.send(f"服务端收到的信息为: {info}".encode())

#通信结束,关闭Socket
dataSocket.close()
listenSocket.close()

客户端代码:
#客户端代码

#导入Socket库
from socket import *

#定义配置参数
IP="127.0.0.1"   #服务器IP地址
SEVERT_PORT=50000   #服务器端口号
BUFFERMAX=1024     #可接收最大缓冲区个数

#创建Socket对象
dataSocket=socket(AF_INET,SOCK_STREAM)
#与服务端建立连接
dataSocket.connect((IP,SEVERT_PORT))  #模拟三次握手过程

while True:
    #用户通过中断输入发送信息
    tosend=input(">>  ")  #INPUT输入的内容为字符串形式
    #发送信息为空,退出循环
    if tosend=="":
        break
    #发送消息为Bytes类型,所以需要编码
    dataSocket.send(tosend.encode())

    #等待接收服务端的消息
    recved=dataSocket.recv(BUFFERMAX)
    #如果返回为空Bytes,表明对方一=已关闭了连接,退出循环
    if not recved:
        break
    #打印读取的信息
    print(f"客户端收到的消息为:{recved.decode()}")
#关闭连接
dataSocket.close()

应用消息格式

在这里插入图片描述

TCP协议进行数据通信的时候,可能不会接受完整消息,可能发送的消息也不完整

格式定义的消息
消息头

消息头存放消息的格式数据,比如消息的长度,类型,状态等

消息体

存放具体的传送数据

使用TCP协议传输信息的程序来说,格式定义一定要明确规定消息的边界

TCP协议传输的是字节流,如果消息中没有指定边界或者长度,接收方就不知道一个完整的消息从字节流的哪里开始到哪里结束

指定消息的边界有两种方式:

  • 用特殊字节作为消息的结尾符号

注意:特殊字节在消息内容中不可出现

  • 在消息开头的某个位置,直接指定消息的长度

UDP协议通常不需要指定消息边界,因为UDP是数据包协议,应用程序从SOCKET接受到的必定是发送方发送的完整消息

传送文件

发送文件时,以二进制比特流发送,发送文件正文内容时,发送方应该告诉接收方文件的相关信息(文件名,文件大小),然后再向接受方发送文件的正文内容

客户端代码
#coding=utf-8
import socket
import tqdm  #模拟进度条
import os

#传输数据分隔符
SEPERATOR="<SEPERATOR>"
#服务器属性
IP="127.0.0.1"
PORT=50000

#文件缓冲区的大小
BUFFER_SIZE=256

#传输文件名字
file_name="触控键盘.pdf"
#文件大小
file_size=os.path.getsize(file_name)  #返回文件大小

#创建SOCKET连接
#默认UDP连接
s=socket.socket()
#连接服务器
print(f"服务器连接中{IP}:{PORT}")
s.connect((IP,PORT))
print(f"服务器连接成功")

#发送文件名字和文件大小,必须进行编码处理,因为传递为数据流
s.send(f"{file_name}{SEPERATOR}{file_size}".encode())  #文件名,分隔符,文件大小
#文件体(数据内容)传输
#添加进度条
progress=tqdm.tqdm(range(file_size),f"发送{file_name}",unit="B",unit_divisor=1024)
#打开文件,以二进制读取发送
with open(file_name,"rb") as f:
    for _ in progress:   #进度条
        #读取文件
        bytes_read=f.read(BUFFER_SIZE)
        #如果读完,退出
        if not bytes_read:
            break
        s.sendall(bytes_read)  #sendall:确保即使网络忙碌,数据仍可传输
        progress.update(len(bytes_read))
#关闭资源
s.close()
服务器端代码
#coding=utf-8
import socket
import os
#进度条
import tqdm

#设置服务器配置信息
IP="0.0.0.0"
PORT=50000

#设置缓冲区大小
BUFFER_SIZE=256
#传输数据分隔符
SEPERATOR="<SEPERATOR>"

#创建SOCKET
s=socket.socket()
#绑定端口号
s.bind((IP,PORT))

#设置连接监听最大数量
s.listen(5)
print(f"服务器监听{IP}:{PORT}")

#模拟连接过程
data_socket,addr=s.accept() #data_socket:连接成功,用于数据传输新的socket,addr:建立连接的客户端地址信息

#打印客户端信息
print(f"建立连接的客户端为:{addr}")

#接受信息
receved=data_socket.recv(BUFFER_SIZE).decode()  #注意解码
#获取文件名和文件大小
file_name,file_size=receved.split(SEPERATOR)  #用分隔符分隔开
#从完整路径中提取文件名
file_name="new"+os.path.basename(file_name)
#获取文件大小(接受的为字符串类型)
file_size=int(file_size)

#文件接受处理
progress=tqdm.tqdm(range(file_size),f"接受{file_name}",unit="B",
                   unit_divisor=1024,unit_scale=True)

#读取文件正文内容
with open(file_name,"wb") as f:
    for _ in progress:
        #从客户端读取数据
        bytes_read=data_socket.recv(BUFFER_SIZE)
        #如果没有数据,退出
        if not bytes_read:
            break
        #写入文件
        f.write(bytes_read)
        #更新进度条
        progress.update(len(bytes_read))

#关闭资源
data_socket.close()
s.close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值