记得当时做实验的时候我是满心的卧槽的,因为实验一和实验二简直是天壤之别,我记得在验收前的那个下午,我依然在疯狂改代码。
众所周知,我是一个衷心于摸鱼的小菜鸡,所以我这个代码其实是我在别人代码的基础上改出来的一个,其实理论上我应该bia出来参考的博客的网址的,但是这是好早之前的了我找不到了…
通过本实验,学习采用Socket(套接字)设计简单的网络数据收发程序,理解应用数据包是如何通过传输层进行传送的。
Socket(套接字)是一种抽象层,应用程序通过它来发送和接收数据,就像应用程序打开一个文件句柄,将数据读写到稳定的存储器上一样。一个socket允许应用程序添加到网络中,并与处于同一个网络中的其他应用程序进行通信。一台计算机上的应用程序向socket写入的信息能够被另一台计算机上的另一个应用程序读取,反之亦然。
不同类型的socket与不同类型的底层协议族以及同一协议族中的不同协议栈相关联。现在TCP/IP协议族中的主要socket类型为流套接字(sockets sockets)和数据报套接字(datagram sockets)。流套接字将TCP作为其端对端协议(底层使用IP协议),提供了一个可信赖的字节流服务。一个TCP/IP流套接字代表了TCP连接的一端。数据报套接字使用UDP协议(底层同样使用IP协议),提供了一个"尽力而为"(best-effort)的数据报服务,应用程序可以通过它发送最长65500字节的个人信息。一个TCP/IP套接字由一个互联网地址,一个端对端协议(TCP或UDP协议)以及一个端口号唯一确定。
#客户端的chat
import socket
import sys
import os
ip_port = ('127.0.0.1',9998) #使用9999会提示被占用?
sk = socket.socket()
sk.connect(ip_port)
container = {'key':'','data':''} #文件路径的剪切
while True:
FLAG = input('0.接收文件 1.发送文件 2.进行消息发送\n')
sk.sendall(str(FLAG).encode('utf-8'))
if FLAG=='1': #发送文件,即原本的功能
path = input('path:') # 客户端输入要上传文件的路径
path = 'F:\\\\'+path #F盘的test10031.txt
print('哈哈哈哈哈',path) ##################test
file_name = os.path.basename(path) # 根据路径获取文件名
file_size=os.stat(path).st_size # 获取文件大小
Informf=(file_name+'|'+str(file_size)) #客户端的打包
sk.send(Informf.encode()) # 发送文件名 和 文件大小
# 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)
msg=sk.recv(1024)
print(msg.decode())
send_size = 0
f= open(path,'rb')
Flag = True
while Flag:
if send_size + 1024 >file_size:
data = f.read(file_size-send_size)
Flag = False
else:
data = f.read(1024)
send_size+=1024
sk.send(data)
aaa = sk.recv(1024) #新增接收
print(aaa.decode())
f.close()
elif FLAG=='0' : #接收
message=sk.recv(1024)
print(message.decode(encoding='utf8'))
message = input('path: ')
message = str(message)
# 发送数据 加码
sk.sendall(message.encode('utf-8'))
print('客户端等待...')
#之前的Srv
pre_data = sk.recv(1024).decode()
#获取请求方法、文件名、文件大小
file_name,file_size = pre_data.split('|') #服务器的解包
# 防止粘包,给客户端发送一个信号。
sk.sendall('收到'.encode())
#已经接收文件的大小
recv_size = 0
file_dir = os.path.join('F:\\\\',message) #下载文件路径拼接 ####理论上没错的样子
print('嘿嘿嘿嘿嘿',file_dir)
f = open(file_dir,'wb')
Flag = True
while Flag:
#未上传完毕,
if int(file_size)>recv_size:
#最多接收1024,可能接收的小于1024
data = sk.recv(1024)
recv_size+=len(data)
#写入文件
f.write(data)
#上传完毕,则退出循环
else:
recv_size = 0
Flag = False
sk.sendall('下载完成'.encode()) #新增发送
print('接收成功')
f.close()
#Srv至此
else : #进行信息发送
print('开始进行聊天')
while True:
msg = input("> ")
if msg == 'stop':
sk.send('stop'.encode('utf-8')) #客户端发送停止消息
break
elif not msg:
continue
sk.send(msg.encode('utf-8')) # 客户端发送消息
rev_data = sk.recv(1024) # 客户端接受消息
if not rev_data:
break
print('服务器消息:', rev_data.decode('utf-8'))
sk.close()
#服务端
import socketserver
import os
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
conn = self.request
print ('connected...')
while True:
order = conn.recv(1024).decode(encoding='utf8') #增加读取
print('执行',order)
if order == '1' : #接收文件,即原本的任务
print('服务器等待...')
pre_data = conn.recv(1024).decode()
#获取请求方法、文件名、文件大小
file_name,file_size = pre_data.split('|') #服务器的解包
# 防止粘包,给客户端发送一个信号。
conn.sendall('收到'.encode())
#已经接收文件的大小
recv_size = 0
file_dir = os.path.join('D:\\\\',file_name) #接收的文件路径拼接 #现在没错了
print("啦啦啦啦啦",file_dir) #####test
f = open(file_dir,'wb')
Flag = True
while Flag:
#未上传完毕,
if int(file_size)>recv_size:
#最多接收1024,可能接收的小于1024
data = conn.recv(1024)
recv_size+=len(data)
#写入文件
f.write(data)
#上传完毕,则退出循环
else:
recv_size = 0
Flag = False
conn.sendall('下载完成'.encode()) #添加发送
print('上传成功')
f.close()
if order == '0' : #发送文件
conn.sendall('服务器准备发送文件'.encode('utf-8'))
#原来的Clt
#path = input('path:') # 客户端输入要上传文件的路径
path = conn.recv(1024).decode() #这里路径是从客户端读取的
#file_name = os.path.basename(path) # 根据路径获取文件名
file_name = os.path.join('D:\\\\', path) #拼接 ###########理论上没错
print('耶耶耶耶耶',file_name)
file_size=os.stat(file_name).st_size # 获取文件大小
Informf=(file_name+'|'+str(file_size)) # 包装文件名 和 文件大小
conn.send(Informf.encode()) # 发送
# 为了防止粘包,将文件名和大小发送过去之后,等待服务端收到,直到从服务端接受一个信号(说明服务端已经收到)
bbb=conn.recv(1024).decode()
print(bbb)
send_size = 0
f= open(file_name,'rb')
Flag = True
while Flag:
if send_size + 1024 >file_size:
data = f.read(file_size-send_size)
Flag = False
else:
data = f.read(1024)
send_size+=1024
conn.send(data)
conn.recv(1024) #新增接收
f.close()
if order == '2' :
print('开始进行聊天')
while True:
data = conn.recv(1024) # 接受客户端发送的消息
print('客户端消息:', data.decode('utf-8'))
if not data:
continue
elif data.decode() == 'stop':
print('停止聊天')
break
message = input('> ')
conn.send(message.encode('utf-8')) # 客户端发送消息
instance = socketserver.ThreadingTCPServer(('127.0.0.1',9998),MyServer)
instance.serve_forever()
主要思路就是通过FLAG的值来判断操作:
FLAG=='1’的时候就是发送文件
FLAG=='0’的时候就是接收文件
FLAG=='2’的时候就是信息互发
有些奇奇怪怪的输出不需要在意,当时有bug然后de不出来,就想着通过输出来看在哪一步执行不来…
朴素的程序员往往用最质朴的方法来debug…
我真的会谢…