python - 在 Python 套接字服务器中保存文本登录文件
问题描述
我正在尝试将两个用户之间发送的消息保存在某种文件中,例如 .txt。目标是用户在请求对话记录时,可以从服务器获取它。我不确定如何实现它。有人可以帮忙或给我一些建议。
Here is my client side:
import socket
import select
import errno
import sys, struct
import pickle
from threading import Thread
HEADER_LENGTH = 1024
IP = "127.0.0.1"
PORT = 9669
def pad(package):
return package + [0]*(HEADER_LENGTH-len(package))
def send_login_request(username):
type_pac = 1
package_type = type_pac.to_bytes(1,'big')
print(package_type)
length = len(username)
if length > 1019:
print ("Error: Username too long")
sys.exit()
package = package_type + struct.pack("I", length) + username.encode()
# package = pad(package)
return package
def send_message(recv_id, message):
type_pac = 2
package_type = type_pac.to_bytes(1,"big")
recv_id = recv_id.to_bytes(1,'big')
length = len(message)
if length > 1015:
print('message too long')
sys.exit()
package = package_type + recv_id + struct.pack('I', length) + message.encode()
return package
def send_con_request(conv_id):
type_pac = 3
package_type = type_pac.to_bytes(1,"big")
conv_id = conv_id.to_bytes(1,'big')
length = len(id)
if length > 1015:
print('id too long')
sys.exit()
package = package_type + struct.pack("I", length) + conv_id
return package
# Create a socket
def recv():
try:
message_receiver = client_socket.recv(HEADER_LENGTH).decode()
# Print message
print(f'> /r {message_receiver}')
except IOError as e :
if e.errno != errno.EAGAIN and e.errno != errno.EWOULDBLOCK:
print('Reading error: {}'.format(str(e)))
sys.exit()
# We just did not receive anything
except Exception as e:
# Any other exception - something happened, exit
print('Reading error: {}'.format(str(e)))
sys.exit()
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to a given ip and port
client_socket.connect((IP, PORT))
my_username = input("Username: ")
request = send_login_request(my_username)
print(request)
client_socket.send(request)
username_conf = client_socket.recv(1024).decode()
print(username_conf)
if username_conf == "Welcome to the server":
con_id = int(input("Please enter conversation's id, if don't have one, please enter 0 "))
if con_id == 0:
con_request = send_con_request(con_id)
client_socket.send(con_request)
else:
con_request = send_con_request(con_id)
client_socket.send(con_request)
conversation = client_socket.recv(HEADER_LENGTH).decode()
recv_id = int(input("Please enter receiver's id"))
while True:
# Wait for user to input a message
message = input(f'{my_username} > ')
# If message is not empty - send it
if message:
message = send_message(recv_id,message)
client_socket.send(message)
recv_thread = Thread(target=recv)
recv_thread.start()
这是我的服务器:
import socket
import select
import struct
import sys
import pickle
HEADER_LENGTH = 1024
conversation ={
(1,2) : '1.txt',
(3,4) : '2.txt'
}
users = [
{
'username': 'user1',
'user_id': 1
},
{
'username': 'user2',
'user_id': 2
},
{
'username': 'user3',
'user_id': 3
},
{
'username': 'user4',
'user_id': 4
},
{
'username': 'user5',
'user_id': 5
}
]
def login(username):
for user in users:
print (user["username"])
if user['username'] == username:
# print ("ok")
return user['username'], user["user_id"]
return None
IP = "127.0.0.1"
PORT = 9669
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind((IP, PORT))
server_socket.listen()
# List of sockets for select.select()
sockets_list = [server_socket]
# List of connected clients - socket as a key, user header and name as data
clients_socket = {}
sessions = {}
def getRecvSocket(user_id):
try:
return sessions[user_id]
except:
return None, None
def sendErrorMes(socketid, mes):
package = [9]
length = len(mes)
if length > 1019:
length = 1019
package += struct.pack("I", length)
package += mes
print(f'Listening for connections on {IP}:{PORT}...')
# Handles message receiving
def receive_message(client_socket):
try:
receive_message = client_socket.recv(HEADER_LENGTH)
return receive_message
except:
return False
while True:
read_sockets, _, exception_sockets = select.select(sockets_list, [], sockets_list)
# Iterate over notified sockets
for notified_socket in read_sockets:
# If notified socket is a server socket - new connection, accept it
if notified_socket == server_socket:
client_socket, client_address = server_socket.accept()
sockets_list.append(client_socket)
else:
# Receive message
package = receive_message(notified_socket)
package_type = package[0]
if package_type == 1:
size = struct.unpack("I", package[1:5])
if size[0] > 1019:
continue
username = package[5:5+size[0]]
username = username.decode()
user,id = login(username)
if login(username) == None:
notified_socket.send(b"no user found")
else:
sessions[id] = notified_socket
print(sessions)
print ("ok")
notified_socket.send((b"Welcome to the server"))
elif package_type == 2:
recv_id = package[1]
size = struct.unpack("I", package[2:6])
if size[0] > 1015:
continue
# recv_id = package_recv[1]
if getRecvSocket(recv_id) == None:
sendErrorMes(notified_socket, "User is offline")
else:
message = package[6:6+size[0]]
message = message.decode()
print(message)
# message = package_recv[2]
# for socket in sessions.values():
# print(sessions)
# print(notified_socket)
# if socket == notified_socket:
# print('ok')
# user = sessions[notified_socket]
# print(user)
# print(f'Received message from {user}, {message}')
# fIterate over connected clients and broadcast message
for client_socket in sessions.values():
print(notified_socket)
# if clients[client_socket
# ] == receive_user and client_socket != notified_socket:
# But don't sent it to sender
if client_socket != notified_socket and client_socket == sessions[recv_id]:
# Send user and message (both with their headers)
# We are reusing here message header sent by sender, and saved username header send by user when he connected
# a = sessions[notified_socket]
# b = recv_id
# with open(f"{conversation[a,b]}.txt", "w"):
# f.write(user + message)
client_socket.send((message).encode())
if message is False:
# print('Closed connection from: {}'.format(user))
# Remove from list for socket.socket()
sockets_list.remove(notified_socket)
# Remove from our list of users
del clients_socket[notified_socket]
continue
elif package_type == 3:
size = struct.unpack("I", package[1:5])
if size[0] > 1019:
continue
convo_id = package[5:5+size[0]]
# convo_id = convo_id.decode()
# convo_id = package_recv[2]
if convo_id in conversation:
with open(conversation[convo_id], 'rb') as file_to_send:
for data in file_to_send:
notified_socket.sendall(data)
print('send successful')
else:
f = open(f"{len(conversation)+1}.txt", "w+")
感谢帮助。
解决方案
推荐阅读
- javascript - 正文点击元素原生js
- awk - 使用 awk 仅从第一个实例获取信息
- c++ - 将自定义命令行参数传递给 Rust 测试
- python - 如何使用线程将多个 keras 模型加载到 python 字典中?
- java - 如何获取文件夹内所有文件的列表
- java - 如何将 test-project 打包到具有 spring 依赖项的可执行 jar 中?
- macos - 在不使用 Homebrew 或完整 XCode 的情况下在 Mac OS 上安装 FreeRDP
- python - python3.9从函数内部更改全局变量值不起作用
- flutter - 伙计们关于如何在 Flutter(Android)中获取 BluetoothDevice 的硬件地址的任何想法。我正在使用 FlutterBlue
- php - Laravel Cookies 因无效域而被拒绝