Python基于TCP套接字实现局域网内图片传输
本文介绍如何使用Python的socket库通过TCP协议在局域网内传输图片。代码分为发送端与接收端,利用struct模块打包文件名与大小,通过二进制流分块传输文件数据。文章详细解析了Socket创建、连接、数据打包及文件读写逻辑,适用于Python3环境,支持本地回环地址或指定局域网IP进行通信。
Python局域网图片传输概述
简述
利用Python的网络套接字(Socket)功能,可以实现图片数据的传输。这一机制在实际应用中具有一定的趣味性。
下文将采用TCP协议进行具体实现,该方案适用于Python3版本。
代码功能简述
具体代码实现如下:
- 发送端(Sender)负责在一台计算机上发起图片发送操作。
- 接收端(Receiver)负责在另一台计算机上,或者同一台计算机的不同端口上接收图片数据。
- 程序逻辑设计为单次发送与单次接收。
- 接收到的新图片文件名会在原文件名基础上增加“new_”前缀。
- 运行顺序有严格要求:必须先启动接收端代码,随后再启动发送端代码。若顺序颠倒,发送端连接将被拒绝。
- 代码默认配置为在同一台计算机上运行,IP地址设置为127.0.0.1。若需跨计算机传输,请将IP地址修改为目标计算机的局域网IP。
- 该程序仅适用于同一局域网环境。若需通过广域网传输,必须使用广域网IP地址并进行相应的网络配置。
发送端与接收端代码实现
代码
【后附解析】
Sender.py (发送者)
import socket
import os
import sys
import struct
def sock_client():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 6666))
except socket.error as msg:
print(msg)
print(sys.exit(1))
while True:
filepath = input('input the file: ')
# filepath = 'test.png'
fhead = struct.pack(b'128sl', bytes(os.path.basename(filepath), encoding='utf-8'), os.stat(filepath).st_size)
s.send(fhead)
print('client filepath: {0}'.format(filepath))
fp = open(filepath, 'rb')
while 1:
data = fp.read(1024)
if not data:
print('{0} file send over...'.format(filepath))
break
s.send(data)
s.close()
break
if __name__ == '__main__':
sock_client()
Reciever.py (接受者)
import socket
import os
import sys
import struct
def socket_service():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 6666))
s.listen(10)
except socket.error as msg:
print(msg)
sys.exit(1)
print("Wait")
while True:
sock, addr = s.accept()
deal_data(sock, addr)
break
s.close()
def deal_data(sock, addr):
print("Accept connection from {0}".format(addr))
while True:
fileinfo_size = struct.calcsize('128sl')
buf = sock.recv(fileinfo_size)
if buf:
filename, filesize = struct.unpack('128sl', buf)
fn = filename.decode().strip('\x00')
new_filename = os.path.join('./', 'new_' + fn)
recvd_size = 0
fp = open(new_filename, 'wb')
while not recvd_size == filesize:
if filesize - recvd_size > 1024:
data = sock.recv(1024)
recvd_size += len(data)
else:
data = sock.recv(1024)
recvd_size = filesize
fp.write(data)
fp.close()
sock.close()
break
if __name__ == '__main__':
socket_service()
代码逻辑详细解析
解析:
发送者代码逻辑:
首先创建TCP套接字,并尝试发起连接。
具体实现代码如下:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 6666))
except socket.error as msg:
print(msg)
print(sys.exit(1))
随后的While循环负责执行图片数据的发送过程。
- 使用struct库对数据进行打包,并通过套接字对象进行发送。
- 注意:网络上部分示例代码不可直接复用,例如此处必须将字符串转换为bytes类型才能发送。
- 利用os库获取文件的基本名称,此举旨在避免因文件路径中包含特殊字符或具体路径信息导致的问题。
- 利用os库获取文件的大小,通过查询文件状态信息中的大小属性获得。
fhead = struct.pack(b'128sl', bytes(os.path.basename(filepath), encoding='utf-8'), os.stat(filepath).st_size)
s.send(fhead)
随后以二进制方式读取文件内容,并分块发送。每次发送固定长度的数据,流程为先读取、判断是否为空、再执行发送。
接受端逻辑:
同样先创建套接字,但此步骤需要绑定特定的IP地址及端口。具体代码如下:(此处设置监听10个套接字连接,但在当前简化代码中并未完全利用该队列机制)。
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 6666))
s.listen(10)
except socket.error as msg:
print(msg)
sys.exit(1)
随后进入循环,判断是否获取到sock对象,此过程会处于阻塞状态等待连接。
在deal_data函数中,通过连接对象开始接收数据。
同样采用无限循环结构,但本质上处理逻辑较为简单,无特殊复杂操作。
接下来处理接收到的文件名。代码中的“128sl”代表打包结构的大小规格(类似于打包箱的尺寸定义),据此生成新的文件名。对应的代码如下:
filename, filesize = struct.unpack('128sl', buf)
fn = filename.decode().strip('\x00')
new_filename = os.path.join('./', 'new_' + fn)
随后的recvd_size变量用于记录已接收数据的大小。程序不断接收数据并写入文件,直到接收完毕,随后关闭文件流。最后关闭套接字并退出循环。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













