首页 > 解决方案 > 在 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+")
         

感谢帮助。

标签: pythonsocketstcp

解决方案


推荐阅读