SOCKET编程实现Client/Server程序python
题目
使用基本的套接字编程技术,以一对基本的TCP协议通信程序为基础,模拟比特洪流(BitTorrent)的分散传输技术完成一个文件的正确传输,使用标准C语言编程。本实验的目的并不是做一个实用的网络程序,而是更好地理解套接字编程原理和P2P技术,重点在特定条件下的实验方案的设计并予以实现。
实验时4个人一组,实现从3个Peer传输同一个文件的不同块到一个Peer。尽可能模拟比特洪流(BitTorrent)技术,将文件划分成指定大小的很多块,理论上不同文件块可以从不同的Peer处下载,要求每个数据源Peer必须向目的Peer传输3个以上文件块,单个Peer传输的块数也不要太多,以免产生太多网络数据块,不利于下一个实验进行数据收集。
建议传输一个图形文件,最终文件内容传输正确是第一位的,图形文件容易验证。
BitTorrent协议是一种P2P技术,属于应用层协议,其主要内容可以结合参看理论课教材上的相关内容,在实现文件传输时主要聚焦在多个Peer向一个Peer传输文件,围绕这个核心功能展开实验方案的设计。
题目理解
因为当时做的时候压根连题目都没看,只是听老师讲的传一个图片,三个client一个Server,分成10块,于是就这么写了。
至于 Peer 比特洪流 文件块 ,这里统统没有。我将图片作压缩成一维数组,分别存入10个txt文件中,通过“使用基本的套接字编程技术,以一对基本的TCP协议通信程序为基础”从client发送到Server,最后再在Server端合并。
这个做法使得文件传输受到限制,只能传特定格式的图片文件,也是本次实验不足的地方。
主要工作
“使用基本的套接字编程技术,以一对基本的TCP协议通信程序为基础”这个过程是参考别人的代码。
主要工作在分组和合并。
在本机上尝试分组合并
准备
1.创建一个文件,并添加代码。(如图中p2p)
2.把图片添加进来
3.删除分组合并.py中保存分片数据的注释,并修改test_save与np.loaddata的路径。
4.点击运行
5.运行结束后建议把去掉的注释补回。
代码
Client
#!coding=utf-8
import socket
import os
import sys
import struct
def socket_client(t):
for i in range(t):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9001))
except socket.error as msg:
print(msg)
sys.exit(1)
print(s.recv(1024))
# 需要传输的文件路径
filepath = 'D:\\Users\\text{}.txt'.format(i)
# 判断是否为文件
if os.path.isfile(filepath):
# 定义定义文件信息。128s表示文件名为128bytes长,l表示一个int或log文件类型,在此为文件大小
fileinfo_size = struct.calcsize('128sl')
# 定义文件头信息,包含文件名和文件大小
fhead = struct.pack('128sl', os.path.basename(filepath).encode('utf-8'), os.stat(filepath).st_size)
# 发送文件名称与文件大小
s.send(fhead)
# 将传输文件以二进制的形式分多次上传至服务器
fp = open(filepath, 'rb')
while 1:
data = fp.read(1024)
if not data:
print('{0} file send over...'.format(os.path.basename(filepath)))
break
s.send(data)
# 关闭当期的套接字对象
s.close()
if __name__ == '__main__':
socket_client(10)
Server
#!coding=utf-8
import sys
import threading
import socket
import struct
def socket_service():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定端口为9001
s.bind(('127.0.0.1', 9001))
# 设置监听数
s.listen(10)
except socket.error as msg:
print(msg)
sys.exit(1)
print('Waiting connection...')
while 1:
# 等待请求并接受(程序会停留在这一旦收到连接请求即开启接受数据的线程)
conn, addr = s.accept()
# 接收数据
t = threading.Thread(target=deal_data, args=(conn, addr))
t.start()
def deal_data(conn, addr):
print('Accept new connection from {0}'.format(addr))
# conn.settimeout(500)
# 收到请求后的回复
conn.send('Hi, Welcome to the server!'.encode('utf-8'))
while 1:
# 申请相同大小的空间存放发送过来的文件名与文件大小信息
fileinfo_size = struct.calcsize('128sl')
# 接收文件名与文件大小信息
buf = conn.recv(fileinfo_size)
# 判断是否接收到文件头信息
if buf:
# 获取文件名和文件大小
filename, filesize = struct.unpack('128sl', buf)
fn = filename.strip(b'\00')
fn = fn.decode()
print('file new name is {0}, filesize if {1}'.format(str(fn), filesize))
recvd_size = 0 # 定义已接收文件的大小
# 存储在该脚本所在目录下面
fp = open('./' + str(fn), 'wb')
print('start receiving...')
# 将分批次传输的二进制流依次写入到文件
while not recvd_size == filesize:
if filesize - recvd_size > 1024:
data = conn.recv(1024)
recvd_size += len(data)
else:
data = conn.recv(filesize - recvd_size)
recvd_size = filesize
fp.write(data)
fp.close()
print('end receive...')
# 传输结束断开连接
conn.close()
break
if __name__ == "__main__":
socket_service()
分组与合并
注意要将图片放到程序目录下。且要保证图片后缀名为jpg,行数能被10整除。
import cv2
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
def text_save(filename, data):#filename为写入文件的路径,data为要写入数据列表.
file = open(filename,'w')
for i in range(len(data)):
s = str(data[i]).replace('[','').replace(']','')#去除[],这两行按数据不同,可以选择
s = s.replace("'",'').replace(',','') +'\n' #去除单引号,逗号,每行末尾追加换行符
file.write(s)
file.close()
print("保存文件成功")
#分片
#当x*y*z不能被10整除?当y不能被10整除?
img = cv2.imread("1.jpg")
#img = cv2.imread("D:\\Users\\1.jpg")
#大小为 1166400*3 img.shape[1] * img.shape[0]*3
x = img.shape[2] #维度
y = img.shape[1] #行
z = img.shape[0] #列
#保存分片数据
'''
print(x)
print(y)
print(z)
img = (img.reshape(img.shape[2] * img.shape[1] * img.shape[0]))
print(img.shape)
#plt.imshow(img)
for i in range(10):
text_save('D:\\Users\\text{}.txt'.format(i),img[i*(int(x*y*z/10)):(i+1)*(int(x*y*z/10))]) #大小的1/10
#plt.show()
'''
#合并
sum=[]
#分组读取
for i in range(10):
k = np.loadtxt('D:\\Users\\text{}.txt'.format(i))
#k = np.loadtxt('text{}.txt'.format(i))
#读取文件每次读取1080为一行,读取108次
for j in range(int(y/10)):
#print('{},{}'.format(i,j))
sum.append(k[j*z*x:(j+1)*z*x])
sum = np.array(sum, dtype = int)
sum1=np.array(sum).reshape(y,z,x)
cv2.imwrite('1.jpg',sum1)
#sum = (sum.reshape(sum.shape[1] * sum.shape[0]))
#text_save('D:\\Users\\1.txt',sum)
sum1 = cv2.imread('1.jpg')
sum1 = cv2.cvtColor(sum1, cv2.COLOR_BGR2RGB) #bgr转rgb
plt.imshow(sum1)
plt.show()
代码参考
使用基本的套接字编程技术,以一对基本的TCP协议通信程序为基础
不好意思,找不到那片博客了,直接用我的就行。