客户端用来发送
import socket
import os
import sys
import struct
socket
网络通信功能os
与操作系统交互功能sys
对解释器的访问和系统相关功能struct
处理二进制数据打包和解包
def sock_client_image():
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.8.183', 6666))
except socket.error as msg:
print(msg)
print(sys.exit(1))
是一个 sock_client_image
用于创建一个客户端套接字并连接服务器用 socket.socket
创建套接字对象 s
通过 s.connect
连接服务器的 IP 地址和端口号
如果连接发生错误打印错误信息退出程序
filepath = input('input the file:')
fhead = struct.pack(b'128sq', bytes(os.path.basename(filepath), encoding='utf-8'),
os.stat(filepath).st_size)
s.send(fhead)
用 input
获取用户输入文件路径存储在 filepath
变量中
用 struct.pack
将文件名和文件大小打包为二进制数据 fhead
os.path.basename
获取文件名 os.stat(filepath).st_size
获取文件大小
用 s.send
将打包后数据 fhead
发送服务器
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()
用 open
函数以二进制读取打开用户输入文件
用一个循环读取文件数据使用 s.send
将数据发送到服务器每次读取 1024 字节并判断是否读取完文件如果读取完打印发送完成并退出循环
最后用 s.close
关闭套接字连接
if __name__ == '__main__':
sock_client_image()
这是入口点在 if __name__ == '__main__':
条件下执行:
调用 sock_client_image
启动客户端程序
服务器用来接收
import socket
import os
import sys
import struct
socket
网络通信功能os
与操作系统交互功能sys
对解释器的访问和系统相关功能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.26', 8899))
s.listen(10)
except socket.error as msg:
print(msg)
sys.exit(1)
print("Wait for Connection...........................")
while True:
sock, addr = s.accept()
deal_image(sock, addr)
是一个 socket_service_image
用于创建服务器套接字并监听 IP 地址和端口号
用 socket.socket
创建套接字对象 s
通过 s.setsockopt
设置套接字选项可以重用地址
用 s.bind
绑定服务器 IP 地址和端口号并用 s.listen
方法开始监听连接请求
如果创建和绑定套接字发生错误打印错误信息并退出程序
在无限循环中用 s.accept
接受客户端连接请求并返回一个新套接字对象 sock
和客户端地址 addr
用 deal_image
来处理收到图片数据
def deal_image(sock, addr):
print("Accept connection from {0}".format(addr)) # 查看发送端的ip和端口
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.recy(1024)
recvd_size += len(data)
else:
data = sock.recv(1024)
recvd_size = filesize
fp.write(data)
fp.close()
sock.close()
break
deal_image
用于处理收到的图片数据首先打印发送端的 IP 地址和端口号
用 struct.calcsize
计算文件名和文件大小的大小用 sock.recv
接收
如果接收到数据用 struct.unpack
解包获取文件名和文件大小根据文件名在服务器端新建一个文件名并打开以二进制写入
用循环来接收文件数据直到收到数据大小等于文件大小如果剩余数据大于 1024 字节用 sock.recv
接收数据并将收到数据写入文件如果剩余数据小于等于 1024 字节直接接收剩余数据并将收到的数据写入文件
最后关闭文件和套接字连接
if __name__ == '__main__':
socket_service_image()
是程序的入口点在 if __name__ == '__main__':
条件下执行:
调用 socket_service_image
启动服务器程序