macos + python3
调用requests库,可以获得url信息
r.content中包含了html内容,然后将其写入file之中
url = input('Enter a URL: ')
r = requests.get(url)
# 下载网页
with open('url_download.html', 'wb') as f:
f.write(r.content)
还可以打印网页中的相关信息
# 打印网页相关信息
print('网页URL: ',r.url)
print('网页状态码: ',r.status_code)
print('网页编码方式: ',r.encoding)
# print('网页内容: ',r.text)
print('网页header:', r.headers)
print('网页大小: {:.4} KB, {} bytes.'.format(len(r.content)/(1024), len(r.content)))
代码汇总:url_download.py
import requests
if __name__ == '__main__':
url = input('Enter a URL: ')
r = requests.get(url)
# 下载网页
with open('url_download.html', 'wb') as f:
f.write(r.content)
# 打印网页相关信息
print('网页URL: ',r.url)
print('网页状态码: ',r.status_code)
print('网页编码方式: ',r.encoding)
# print('网页内容: ',r.text)
print('网页header:', r.headers)
print('网页大小: {:.4} KB, {} bytes.'.format(len(r.content)/(1024), len(r.content)))
输入一个网址:
可以看到网页的相关信息,并且将网页下载下来
首先编写客户端代码:
指定服务端IP(本机localhost)以及端口(12000),并且建立TCP连接
from socket import *
serverName = 'localhost'
serverPort = 12000
print('The client is ready to connect')
print('Client is connecting to {}:{}'.format(serverName, serverPort))
# 建立TCP连接
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
然后开始接受指令信息:
如果指令为非Time/Exit时,显示是非法指令
如果指令为Time/Exit时,向服务端发送指令,并且输出来自服务端的反馈;如果为Exit时,则关闭TCP连接。
while True:
command = input('Input your command (Time / Exit):')
# 指令为Time / Exit
if command == 'Time' or command == 'Exit':
# 向服务器发送指令
clientSocket.send(command.encode())
# 输出来自服务器的信息
modifiedSentence = clientSocket.recv(1024)
print('From Server: {}'.format(modifiedSentence.decode()))
# 指令为EXIT时,结束TCP连接
if command == 'Exit':
clientSocket.close()
break
# 非法指令
else:
print('Invalid command')
然后编写服务端代码:
指定服务端端口为12000,并且开启监听
from socket import *
import time
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
print('The server is ready to connect')
建立TCP连接监听后,然后开始等待客户端的连接
while True:
# 等待客户端连接
print('-----------------------------------------------------')
print('Waiting for connection...')
# 接收客户端连接
connectionSocket, addr = serverSocket.accept()
print('Connected to {}'.format(addr))
pass
建立连接后,接受来自客户端的指令
如果为Time,则返回当前时间
如果为Exit,则返回“BYE”,并关闭连接
while True:
# 接收客户端发送的指令,并处理指令
command = connectionSocket.recv(1024).decode()
print('Received command: {}'.format(command))
if command == 'Time':
returnMessage = time.asctime(time.localtime(time.time()))
elif command == 'Exit':
returnMessage = 'Bye'
print('Return message: {}'.format(returnMessage))
# 向客户端发送信息
connectionSocket.send(returnMessage.encode())
# 指令为EXIT时,结束TCP连接
if command == 'Exit':
connectionSocket.close()
break
代码汇总:
TCPServer.py
from socket import *
import time
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
print('The server is ready to connect')
while True:
# 等待客户端连接
print('-----------------------------------------------------')
print('Waiting for connection...')
# 接收客户端连接
connectionSocket, addr = serverSocket.accept()
print('Connected to {}'.format(addr))
while True:
# 接收客户端发送的指令,并处理指令
command = connectionSocket.recv(1024).decode()
print('Received command: {}'.format(command))
if command == 'Time':
returnMessage = time.asctime(time.localtime(time.time()))
elif command == 'Exit':
returnMessage = 'Bye'
print('Return message: {}'.format(returnMessage))
# 向客户端发送信息
connectionSocket.send(returnMessage.encode())
# 指令为EXIT时,结束TCP连接
if command == 'Exit':
connectionSocket.close()
break
TCPClient.py
from socket import *
serverName = 'localhost'
serverPort = 12000
print('The client is ready to connect')
print('Client is connecting to {}:{}'.format(serverName, serverPort))
# 建立TCP连接
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
while True:
command = input('Input your command (Time / Exit):')
# 指令为Time / Exit
if command == 'Time' or command == 'Exit':
# 向服务器发送指令
clientSocket.send(command.encode())
# 输出来自服务器的信息
modifiedSentence = clientSocket.recv(1024)
print('From Server: {}'.format(modifiedSentence.decode()))
# 指令为EXIT时,结束TCP连接
if command == 'Exit':
clientSocket.close()
break
# 非法指令
else:
print('Invalid command')
Server端:
Client端:
只要不关闭Server端,就可以一直处理Client端的请求
首先编写客户端代码:
指定服务端IP(本机localhost)以及端口(12000),并且建立TCP连接
serverName = 'localhost'
serverPort = 12000
print('The client is ready to connect')
print('Client is connecting to {}:{}'.format(serverName, serverPort))
# 建立TCP连接
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
建立连接后,服务端会发来可接受文件列表。用户通过输入文件名来选择下载的文件
msg = clientSocket.recv(1024).decode()
filenames = msg.split(',')
print('Choose a file to receive:' + '\n' + '\n'.join(filenames))
filename = input('Input the file names you want to receive:')
将需要下载的文件名发送给服务端,如果返回的信息是OK则开始下载并保存在clientData文件夹下,重命名为new+filename,否则则说明文件不存在。
filename = input('Input the file names you want to receive:')
clientSocket.send(filename.encode())
response = clientSocket.recv(1024).decode()
if response == 'OK':
clientSocket.send('OK'.encode())
# 准备开始接收文件
print('Receiving the File({})...'.format(filename))
# 将文件下载到本地
f = open('clientData/new'+filename, 'wb')
msg = clientSocket.recv(1024).decode()
f.write(msg.encode())
f.close()
print('File({}) received.'.format(filename))
else:
print('File({}) not found.'.format(filename))
clientSocket.close()
print('Client is disconnected.')
然后编写服务器端代码:
指定服务端端口为12000,并且开启监听
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
print('The server is ready to connect')
建立TCP连接监听后,然后开始等待客户端的连接
while True:
# 等待客户端连接
print('-----------------------------------------------------')
print('Waiting for connection...')
# 接收客户端连接
connectionSocket, addr = serverSocket.accept()
print('Connected to {}'.format(addr))
获得Data文件夹下的文件名,并发送给客户端进行选择’
# 获取data文件夹下的文件名
filenames = ''
for filename in os.listdir('serverData'):
filenames += filename + ','
connectionSocket.send(filenames[:-1].encode())
接受来自客户端的申请文件名
filename = connectionSocket.recv(1024).decode()
print("Receiving the filename: {}.".format(filename))
根据文件名,发送文件或者错误信息
if filename in os.listdir('serverData'):
# 申请文件存在
print('{} is in the data folder. ✅'.format(filename))
connectionSocket.send('OK'.encode())
print('Sending the File({})...'.format(filename))
file = open('serverData/'+filename, "r")
data = file.read()
# 客服端准备接收文件
msg = connectionSocket.recv(1024).decode()
connectionSocket.send(data.encode())
print('File({}) sent.'.format(filename))
file.close()
else:
# 申请文件不存在
print('{} is not in the data folder. ❌'.format(filename))
connectionSocket.send('NO'.encode())
connectionSocket.close()
print(f"Connection{addr} disconnected.")
代码汇总:
TCPClient.py
from socket import *
serverName = 'localhost'
serverPort = 12000
print('The client is ready to connect')
print('Client is connecting to {}:{}'.format(serverName, serverPort))
# 建立TCP连接
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName, serverPort))
msg = clientSocket.recv(1024).decode()
filenames = msg.split(',')
print('Choose a file to receive:' + '\n' + '\n'.join(filenames))
filename = input('Input the file names you want to receive:')
clientSocket.send(filename.encode())
response = clientSocket.recv(1024).decode()
if response == 'OK':
clientSocket.send('OK'.encode())
# 准备开始接收文件
print('Receiving the File({})...'.format(filename))
# 将文件下载到本地
f = open('clientData/new'+filename, 'wb')
msg = clientSocket.recv(1024).decode()
f.write(msg.encode())
f.close()
print('File({}) received.'.format(filename))
else:
print('File({}) not found.'.format(filename))
clientSocket.close()
print('Client is disconnected.')
TCPserver.py
from socket import *
import os
serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)
print('The server is ready to connect')
while True:
# 等待客户端连接
print('-----------------------------------------------------')
print('Waiting for connection...')
# 接收客户端连接
connectionSocket, addr = serverSocket.accept()
print('Connected to {}'.format(addr))
# 获取data文件夹下的文件名
filenames = ''
for filename in os.listdir('serverData'):
filenames += filename + ','
connectionSocket.send(filenames[:-1].encode())
filename = connectionSocket.recv(1024).decode()
print("Receiving the filename: {}.".format(filename))
if filename in os.listdir('serverData'):
# 申请文件存在
print('{} is in the data folder. ✅'.format(filename))
connectionSocket.send('OK'.encode())
print('Sending the File({})...'.format(filename))
file = open('serverData/'+filename, "r")
data = file.read()
# 客服端准备接收文件
msg = connectionSocket.recv(1024).decode()
connectionSocket.send(data.encode())
print('File({}) sent.'.format(filename))
file.close()
else:
# 申请文件不存在
print('{} is not in the data folder. ❌'.format(filename))
connectionSocket.send('NO'.encode())
connectionSocket.close()
print(f"Connection{addr} disconnected.")
首先在Data文件中存放一些文件,clientData为空
下载成功:
下载失败:(文件不存在)
首先编写客户端代码:
建立两个线程,一个线程用于接受信息,一个线程用于发送信息
def __init__(self, name, client_post, server_post):
# 初始化
self.ClientPort = client_post
self.ServerPost = server_post
self.udp_socket = socket(AF_INET, SOCK_DGRAM)
self.userName = name
self.thread_rece = Thread(target=self.recv_msg)
self.thread_send = Thread(target=self.send_msg)
def start(self):
# 运行
self.udp_socket.bind(self.ClientPort)
data_info = self.userName+' -n'
self.udp_socket.sendto(data_info.encode('gb2312'), self.ServerPost)
print(self.getTime(), '系统:您已加入聊天')
self.thread_rece.start()
self.thread_send.start()
self.thread_rece.join()
self.thread_send.join()
接受信息:
接受来自服务端发送的信息,如果为exit则关闭TCP连接,否则展示信息。
def recv_msg(self):
# 接收信息
while True:
recv_data, dest_ip = self.udp_socket.recvfrom(
1024) # 1024 表示接收最大字节 防止内存溢出
if recv_data.decode("gb2312") == 'exit' and dest_ip == self.ServerPost:
print(self.getTime(), '客户端已退出')
self.udp_socket.close()
break
print(recv_data.decode("gb2312"))
发送信息:
根据输入,发送信息给服务端
def send_msg(self):
# 发送信息
while True:
data_info = input()
self.udp_socket.sendto(data_info.encode('gb2312'), self.ServerPost)
if data_info == 'exit':
break
辅助函数:(返回时间)
def getTime(self):
# 返回时间
return '['+time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+']'
然后编写服务端代码:
准备以下数据结构记录相关信息
user_name = {} # dict 用户名:ip地址
user_ip = {} # dict ip地址:用户名
__ServerOpen = True # 服务器开关
建立两个线程,一个线程用于接受信息,一个线程用于发送信息
self.thread_rece = Thread(target=self.recv_msg)
self.thread_send = Thread(target=self.send_msg)
def start(self):
print(self.getTime(), '服务端已启动')
self.thread_rece.start()
self.thread_send.start()
self.thread_rece.join()
self.thread_send.join()
data_info = self.getTime()+' 系统:'+info_list[0] + '加入了聊天'
self.sent_to_all(data_info)
self.user_name[info_list[0]] = dest_ip
self.user_ip[dest_ip] = info_list[0]
# 向所有用户发送消息
def sent_to_all_notMe(self, name, data_info):
# 广播消息除了指定用户
for i in self.user_name.keys():
if i != name:
self.udp_socket.sendto(
data_info.encode('gb2312'), self.user_name[i])
向所有客户端发送信息:(系统广播)
# 向所有用户发送消息
def sent_to_all(self, data_info):
for i in self.user_ip.keys():
self.udp_socket.sendto(data_info.encode('gb2312'), i)
# 接收信息
while True:
recv_data, dest_ip = self.udp_socket.recvfrom(
1024) # 1024 表示接收最大字节 防止内存溢出
这里我定义了三种信息格式:
message -t name: 发送信息message给name(类似私聊)
message -ta: 将信息message群发给当前聊天室中所有成员
exit: 退出聊天室
因此在收到信息后,我们需要首先对信息进行解析,确认信息为哪一种格式
info_list = str(recv_data.decode("gb2312")).split(' ') # 切割命令
① message -t name
# 向指定用户发送私聊
elif info_list[-2] == '-t':
if info_list[-1] not in self.user_name.keys(): # 目前查询不到目标用户,向发送用户发起警告
data_info = self.getTime()+' 系统:发送失败!用户不存在!'
self.udp_socket.sendto(data_info.encode('gb2312'), dest_ip)
continue
dest_port = self.user_name[info_list[-1]] # 接收方端口
data_info = self.getTime(
)+' %s:' % self.user_ip[dest_ip]+' '.join(info_list[:-2]) # 需发送的信息
self.udp_socket.sendto(data_info.encode('gb2312'), dest_port)
② message -ta
# 向所有用户发送消息
elif info_list[-1] == '-ta':
name = self.user_ip[dest_ip]
data_info = self.getTime()+' %s:' % name + \
' '.join(info_list[:-1])
self.sent_to_all_notMe(name, data_info)
③ exit
# 用户退出聊天室
if str(recv_data.decode("gb2312")) == 'exit':
self.udp_socket.sendto('exit'.encode('gb2312'), dest_ip)
name = self.user_ip.pop(dest_ip)
self.sent_to_all(self.getTime()+' 系统:%s已退出聊天' % name)
def send_msg(self):
while self.__ServerOpen:
data_info = input()
if data_info == 'exit':
self.__ServerOpen = False
print(self.getTime(), '服务端关闭中,等待所有用户下线')
self.sent_to_all(self.getTime()+' 服务器系统已关闭,请自行下线')
break
然后等待所有客户端都退出聊天室后,在关闭连接。
# 服务器关闭后就停止接收客户端信息,等待所有用户退出
if not self.__ServerOpen:
self.udp_socket.sendto('exit'.encode('gb2312'), dest_ip)
# 从用户列表中删除用户
name = self.user_ip.pop(dest_ip)
self.sent_to_all(self.getTime()+' 系统:%s已退出聊天' % name)
# 等待所有用户退出聊天室
while len(self.user_ip):
recv_data, dest_ip = self.udp_socket.recvfrom(1024)
self.udp_socket.sendto('exit'.encode('gb2312'), dest_ip)
# 从用户列表中删除用户
name = self.user_ip.pop(dest_ip)
self.sent_to_all(self.getTime()+' 系统:%s已退出聊天' % name)
# 关闭聊天室
print(self.getTime(), '服务端已关闭')
self.udp_socket.close()
break
代码汇总:
server.py
from socket import *
from threading import Thread
import time
class Server():
user_name = {} # dict 用户名:ip地址
user_ip = {} # dict ip地址:用户名
__ServerOpen = True # 服务器开关
def __init__(self, post):
self.ServerPort = post
self.udp_socket = socket(AF_INET, SOCK_DGRAM)
# 服务器端口
self.udp_socket.bind(self.ServerPort)
self.thread_rece = Thread(target=self.recv_msg)
self.thread_send = Thread(target=self.send_msg)
def start(self):
print(self.getTime(), '服务端已启动')
self.thread_rece.start()
self.thread_send.start()
self.thread_rece.join()
self.thread_send.join()
def recv_msg(self):
# 接收信息
while True:
recv_data, dest_ip = self.udp_socket.recvfrom(
1024) # 1024 表示接收最大字节 防止内存溢出
# 服务器关闭后就停止接收客户端信息,等待所有用户退出
if not self.__ServerOpen:
self.udp_socket.sendto('exit'.encode('gb2312'), dest_ip)
# 从用户列表中删除用户
name = self.user_ip.pop(dest_ip)
self.sent_to_all(self.getTime()+' 系统:%s已退出聊天' % name)
# 等待所有用户退出聊天室
while len(self.user_ip):
recv_data, dest_ip = self.udp_socket.recvfrom(1024)
self.udp_socket.sendto('exit'.encode('gb2312'), dest_ip)
# 从用户列表中删除用户
name = self.user_ip.pop(dest_ip)
self.sent_to_all(self.getTime()+' 系统:%s已退出聊天' % name)
# 关闭聊天室
print(self.getTime(), '服务端已关闭')
self.udp_socket.close()
break
print(self.getTime(), dest_ip, recv_data)
info_list = str(recv_data.decode("gb2312")).split(' ') # 切割命令
# 用户退出聊天室
if str(recv_data.decode("gb2312")) == 'exit':
self.udp_socket.sendto('exit'.encode('gb2312'), dest_ip)
name = self.user_ip.pop(dest_ip)
self.sent_to_all(self.getTime()+' 系统:%s已退出聊天' % name)
# 向指定用户发送私聊
elif info_list[-2] == '-t':
if info_list[-1] not in self.user_name.keys(): # 目前查询不到目标用户,向发送用户发起警告
data_info = self.getTime()+' 系统:发送失败!用户不存在!'
self.udp_socket.sendto(data_info.encode('gb2312'), dest_ip)
continue
dest_port = self.user_name[info_list[-1]] # 接收方端口
data_info = self.getTime(
)+' %s:' % self.user_ip[dest_ip]+' '.join(info_list[:-2]) # 需发送的信息
self.udp_socket.sendto(data_info.encode('gb2312'), dest_port)
# 新用户注册
elif info_list[-1] == '-n':
data_info = self.getTime()+' 系统:'+info_list[0] + '加入了聊天'
self.sent_to_all(data_info)
self.user_name[info_list[0]] = dest_ip
self.user_ip[dest_ip] = info_list[0]
# 向所有用户发送消息
elif info_list[-1] == '-ta':
name = self.user_ip[dest_ip]
data_info = self.getTime()+' %s:' % name + \
' '.join(info_list[:-1])
self.sent_to_all_notMe(name, data_info)
# 向所有用户发送消息
def sent_to_all(self, data_info):
for i in self.user_ip.keys():
self.udp_socket.sendto(data_info.encode('gb2312'), i)
# 向所有用户发送消息
def sent_to_all_notMe(self, name, data_info):
# 广播消息除了指定用户
for i in self.user_name.keys():
if i != name:
self.udp_socket.sendto(
data_info.encode('gb2312'), self.user_name[i])
def getTime(self):
return '['+time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+']'
def send_msg(self):
while self.__ServerOpen:
data_info = input()
if data_info == 'exit':
self.__ServerOpen = False
print(self.getTime(), '服务端关闭中,等待所有用户下线')
self.sent_to_all(self.getTime()+' 服务器系统已关闭,请自行下线')
break
if __name__ == '__main__':
server1 = Server(('127.0.0.1', 12000))
server1.start()
client.py
from socket import *
from threading import Thread
import time
class Client():
def __init__(self, name, client_post, server_post):
# 初始化
self.ClientPort = client_post
self.ServerPost = server_post
self.udp_socket = socket(AF_INET, SOCK_DGRAM)
self.userName = name
self.thread_rece = Thread(target=self.recv_msg)
self.thread_send = Thread(target=self.send_msg)
def start(self):
# 运行
self.udp_socket.bind(self.ClientPort)
data_info = self.userName+' -n'
self.udp_socket.sendto(data_info.encode('gb2312'), self.ServerPost)
print(self.getTime(), '系统:您已加入聊天')
self.thread_rece.start()
self.thread_send.start()
self.thread_rece.join()
self.thread_send.join()
def recv_msg(self):
# 接收信息
while True:
recv_data, dest_ip = self.udp_socket.recvfrom(
1024) # 1024 表示接收最大字节 防止内存溢出
if recv_data.decode("gb2312") == 'exit' and dest_ip == self.ServerPost:
print(self.getTime(), '客户端已退出')
self.udp_socket.close()
break
print(recv_data.decode("gb2312"))
def send_msg(self):
# 发送信息
while True:
data_info = input()
self.udp_socket.sendto(data_info.encode('gb2312'), self.ServerPost)
if data_info == 'exit':
break
def getTime(self):
# 返回时间
return '['+time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+']'
if __name__ == '__main__':
Postnum = int(input('我方使用端口号: '))
name = input('我方用户名: ')
client = Client(name, ('127.0.0.1', Postnum), ('127.0.0.1', 12000))
client.start()
首先展示群发功能
这是每个客户端的界面展示,可以看见每个用户都向聊天室发送了一条消息,并成功展示
下方是服务器端的界面展示
然后展示私聊功能
成功:user1向user2发送私聊消息,user3的界面中不会有信息展示
失败:user1向user4发送私聊消息,发现没有该用户
接着随机发送一些消息,并关闭聊天室服务器
服务端:
最后发送exit指令,提示所有用户下线。并且在所有用户下线后,自动结束进程