服务端:
需要导入多个包
import socket
:导入socket模块,用于网络通信。import os
:导入os模块,用于文件操作。import sys
:导入sys模块,用于系统相关操作。import struct
:导入struct模块,用于处理数据的打包和解包。-
def socket_service_image(): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(("192.168.9.190", 6666)) s.listen(10) except socket.error as msg: print(msg) sys.exit(1)
定义一个函数
socket_service_image()
,该函数用于创建并监听socket连接。通过socket.socket()
创建一个TCP/IP套接字对象s
,设置SO_REUSEADDR
选项,绑定到本地IP地址"192.168.9.190"和端口号6666,然后调用s.listen(10)
开始监听。 -
print("Wait for Connection..................")
:打印输出"Wait for Connection..................",表示等待客户端的连接。 -
while True: sock, addr = s.accept() # addr是一个元组(ip,port) deal_image(sock, addr)
使用一个无限循环,调用
s.accept()
方法等待客户端连接,返回一个新的socket对象sock
和客户端地址addr
,然后调用deal_image()
函数处理图像数据。 -
def deal_image(sock, addr): print("Accept cooection from {0}".format(addr))
定义一个函数
deal_image(sock, addr)
,用于处理图像数据。打印输出"Accept connection from {0}",其中{0}
会被客户端地址addr
替代。 -
while True: fileinfo_size = struct.calcsize("128sq") buf = sock.recv(fileinfo_size) if buf: filename , filesize = struct.unpack("128sq",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
在
deal_image()
函数中,使用一个无限循环,首先计算文件信息的大小并存储在fileinfo_size
变量中,然后从socket接收数据并存入buf
中。如果buf
非空,则进行解包操作,将文件名和文件大小解包为filename
和filesize
。将文件名去除空字符并加上前缀"new_",确定新文件的路径。接着,创建一个空文件,并使用循环接收并写入文件数据,直到接收大小等于文件大小。最后关闭文件和socket连接,并结束循环。
10
if __name__ =='__main__':
socket_service_image()
判断当前脚本是否作为主程序运行,如果是,则调用socket_service_image()
函数启动图片传输服务端。
客户端:
import socket
:导入socket模块,用于网络通信。import os
:导入os模块,用于文件操作。import sys
:导入sys模块,用于系统相关操作。import struct
:导入struct模块,用于处理数据的打包和解包。-
def sock_client_image(): while True: try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("192.168.9.190", 6666)) # 服务器和客户端都在一个系统下使用的ip和端口 except socket.error as msg: print(msg) print(sys.exit(1))
定义一个函数sock_client_image()
,该函数用于创建并连接到socket服务器。通过socket.socket()
创建一个TCP/IP套接字对象s
,然后调用s.connect(("192.168.9.190", 6666))
与服务器建立连接。
6.
-
filepath = input("input the file: ")
:接收用户输入,要求用户输入当前目录下的图片名,将其存储在filepath
变量中。
7.
fhead = struct.pack(b'128sq', bytes(os.path.basename(filepath), encoding='utf-8'),
os.stat(filepath).st_size) # 将xxx.jpg以128sq的格式打包
s.send(fhead)
·使用struct.pack()
方法将文件名和文件大小打包为128sq格式的字节流,其中文件名首先使用os.path.basename()
获取,然后通过bytes()
将其编码为utf-8格式。同时使用os.stat(filepath).st_size
获取文件大小,并一起打包为字节流fhead
。最后使用s.send(fhead)
发送文件头部信息。
8
fp = open(filepath, "rb") # 打开要输入的图片
while True:
data = fp.read(1024) # 读入图片数据
if not data:
print("{0} send over....".format(filepath))
break
s.send(data) # 以二进制格式发送图片数据
s.close()
打开指定路径的图片文件,并使用循环读取1024字节的图片数据。如果读取到的数据为空,则表示图片发送完成,打印输出"{0} send over....",其中{0}
会被图片路径替代,并跳出循环。否则,继续发送该1024字节的图片数据。最后关闭文件和socket连接。
9
if __name__ == '__main__':
sock_client_image()
判断当前脚本是否作为主程序运行,如果是,则调用sock_client_image()
函数启动图片传输客户端。