客户端部分
先创建TCP套接字
socket.AF_INET表示使用IPv4地址,
socket.SOCK_STREAM表示使用TCP协议进行通信。
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
通过scoket对象连接服务器IP地址和端口
server_socket.bind((“服务器IP”, 8000))
接着用 struct.pack()函数打包要发送的文件信息,
格式字符串b'128sq'
128s表示一个长度为128字节的字符串,q表示一个长整型数
bytes(os.path.basename(filepath), encoding='utf-8')将文件名转换为utf-8编码的字节对象
os.stat(filepath).st_size获取文件的大小。
filepath = input('input the file:')
fead = struct.pack(b'128sq', bytes(os.path.basename(filepath), encoding='utf-8'),os.stat(filepath).st_size)
一些功能方法:
s.send(fead):使用socket对象s将打包好的文件信息发送到服务器。
fp = open(filepath, 'rb'):以二进制读取模式打开用户指定的文件,创建一个文件对象fp。
while True::进入一个无限循环,直到文件读取完毕。
data = fp.read(1024):从文件对象fp中读取1024字节(1KB)的数据,并将其保存在变量data中。
if not data::如果读取的数据为空,说明文件已经读取完毕,跳出循环。
s.send(data):使用socket对象s将读取的数据发送到服务器。
print('{0} send over...'.format(filepath)):打印传输完成的文件名。
s.close():关闭客户端的socket连接。
s.send(fead)
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()
代码大全举例:
import socket
import os
import sys
import struct
def sock_client_image():
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.9.145', 8888))
except socket.error as msg:
print(msg)
print(sys.exit(1))
filepath = input('input the file:')
fead = struct.pack(b'128sq', bytes(os.path.basename(filepath), encoding='utf-8'),
os.stat(filepath).st_size)
s.send(fead)
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()
if __name__ == '__main__':
sock_client_image()
服务端
一些方法如下:
socket.socket(socket.AF_INET, socket.SOCK_STREAM):首先还是先创建TCP套接字
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1):设置socket选项,使得可以复用绑定的地址和端口。
s.bind(('192.168.56.1', 8888)):连接服务器IP地址和端口
s.listen(10):开始监听客户端连接请求,参数表示可以同时接收的最大连接数。
sys.exit(1)表示通过调用sys模块的exit()函数来终止程序的执行。
sock, addr = s.accept():等待客户端的连接请求,如果有连接请求过来,返回一个新的socket对象sock和客户端的地址信息addr。
deal_image(sock, addr):处理图像数据的函数,将接收到的客户端socket对象和地址信息传递给它。
buf = sock.recv(file_info_size):使用客户端socket对象sock接收指定大小的数据,存储在变量buf中。
filename, filesize = struct.unpack('128sq', buf):使用打包格式'128sq'解析接收到的文件信息,得到文件名和文件大小。
fn = filename.decode().strip('\x00'):将文件名解码为字符串,并去除字符串末尾的空字符。
new_filename = os.path.join('./', 'new_' + fn):生成一个新的文件名,加上前缀new_。
fp = open(new_filename, 'wb'):以二进制写入模式打开新的文件,创建一个文件对象fp。
while not recd_size == filesize::当已接收文件数据的大小不等于文件大小时。
data = sock.recv(1024):接收1024字节的文件数据,并存储在变量data中。
fp.write(data):将接收到的文件数据写入新的文件。
fp.close():关闭文件对象。
sock.close():关闭客户端socket连接。
break:跳出循环,结束函数。
def deal_image(sock, addr):
print("Accept connection from {0}".format(addr))
while True:
file_info_size = struct.calcsize('128sq')
buf = sock.recv(file_info_size)
if buf:
filename, filesize = struct.unpack('128sq', buf)
fn = filename.decode().strip('\x00')
new_filename = os.path.join('./', 'new_' + fn)
recd_size = 0
fp = open(new_filename, 'wb')
while not recd_size == filesize:
if filesize - recd_size > 1024:
data = sock.recv(1024)
recd_size += len(data)
else:
data = sock.recv(1024)
recd_size = filesize
fp.write(data)
fp.close()
sock.close()
break
if __name__ == '__main__':
socket_service_image()