Try the HW5 code out?
This commit is contained in:
parent
cbcb35a158
commit
3206565d55
2 changed files with 136 additions and 5 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
import os
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import select
|
import select
|
||||||
|
|
@ -15,13 +16,25 @@ def main():
|
||||||
SERVER_HOST = sys.argv[1]
|
SERVER_HOST = sys.argv[1]
|
||||||
SERVER_PORT = int(sys.argv[2])
|
SERVER_PORT = int(sys.argv[2])
|
||||||
|
|
||||||
|
# Prompt user for a local directory path for file operations
|
||||||
|
while True:
|
||||||
|
local_path = input("Enter a local directory path for sending/receiving files: ").strip()
|
||||||
|
if os.path.isdir(local_path):
|
||||||
|
print(f"Using directory: {local_path}")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
print("Invalid directory. Please enter a valid path.")
|
||||||
|
|
||||||
# create a socket object
|
# create a socket object
|
||||||
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
try:
|
try:
|
||||||
# connect to the server
|
# connect to the server
|
||||||
client_socket.connect((SERVER_HOST, SERVER_PORT))
|
client_socket.connect((SERVER_HOST, SERVER_PORT))
|
||||||
print(f"Connected to chat server at {SERVER_HOST}:{SERVER_PORT}")
|
print(f"Connected to chat server at {SERVER_HOST}:{SERVER_PORT}")
|
||||||
|
|
||||||
|
# Send the local path to the server
|
||||||
|
client_socket.send(f"SET_PATH {local_path}".encode('utf-8'))
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
# use select to wait for either server messages or user input
|
# use select to wait for either server messages or user input
|
||||||
read_sockets, _, _ = select.select([client_socket, sys.stdin], [], [])
|
read_sockets, _, _ = select.select([client_socket, sys.stdin], [], [])
|
||||||
|
|
@ -33,8 +46,35 @@ def main():
|
||||||
if not server_message:
|
if not server_message:
|
||||||
print("Disconnected from server")
|
print("Disconnected from server")
|
||||||
return
|
return
|
||||||
print(f"\n{server_message}")
|
if server_message.startswith("FILE_REQUEST"):
|
||||||
print("> ", end="", flush=True)
|
# Handle file request
|
||||||
|
_, sending_username, filename = server_message.split()
|
||||||
|
file_path = os.path.join(local_path, filename)
|
||||||
|
if os.path.isfile(file_path):
|
||||||
|
file_size = os.path.getsize(file_path)
|
||||||
|
with open(file_path, "rb") as f:
|
||||||
|
file_bytes = f.read()
|
||||||
|
filetype = "File"
|
||||||
|
client_socket.send(
|
||||||
|
f"@{sending_username}@CLIENT -f {filename} {filetype} {file_size} {file_bytes.decode('latin1')} ENDFILE".encode('utf-8')
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
client_socket.send(
|
||||||
|
f"@{sending_username}@CLIENT -f {filename} NOTFOUND".encode('utf-8')
|
||||||
|
)
|
||||||
|
elif server_message.startswith("FILE_TRANSFER"):
|
||||||
|
# Handle file transfer
|
||||||
|
_, sending_username, filename, filetype, filelength = server_message.split()
|
||||||
|
file_bytes = client_socket.recv(int(filelength))
|
||||||
|
end_marker = client_socket.recv(BUFFER_SIZE).decode('utf-8')
|
||||||
|
if end_marker == "ENDFILE":
|
||||||
|
file_path = os.path.join(local_path, filename)
|
||||||
|
with open(file_path, "wb") as f:
|
||||||
|
f.write(file_bytes)
|
||||||
|
print(f"Received file '{filename}' from {sending_username}.")
|
||||||
|
else:
|
||||||
|
print(f"\n{server_message}")
|
||||||
|
print("> ", end="", flush=True)
|
||||||
else:
|
else:
|
||||||
# prompt for user input
|
# prompt for user input
|
||||||
client_message = input()
|
client_message = input()
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import os
|
||||||
import socket
|
import socket
|
||||||
import select
|
import select
|
||||||
|
|
||||||
|
|
@ -5,6 +6,18 @@ CHATPORT = 8181
|
||||||
BUFFER_SIZE = 1024
|
BUFFER_SIZE = 1024
|
||||||
MAX_CONNECT_QUEUE = 10
|
MAX_CONNECT_QUEUE = 10
|
||||||
|
|
||||||
|
def format_file_info(file_path):
|
||||||
|
"""Helper function to format file information."""
|
||||||
|
file_size = os.path.getsize(file_path)
|
||||||
|
if file_size < 1000:
|
||||||
|
size_str = f"{file_size} B"
|
||||||
|
elif file_size < 1000000:
|
||||||
|
size_str = f"{file_size / 1000:.2f} KB"
|
||||||
|
else:
|
||||||
|
size_str = f"{file_size / 1000000:.2f} MB"
|
||||||
|
file_type = "Directory" if os.path.isdir(file_path) else "File"
|
||||||
|
return f"{os.path.basename(file_path)} - {file_type} - {size_str}"
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# set the flag variable to true for infinite loop
|
# set the flag variable to true for infinite loop
|
||||||
quitFlag = True
|
quitFlag = True
|
||||||
|
|
@ -31,6 +44,8 @@ def main():
|
||||||
# keep track of the states of each client connected, and if they are
|
# keep track of the states of each client connected, and if they are
|
||||||
# technically in an 'unsafe' state like in change username or chatroom mode.
|
# technically in an 'unsafe' state like in change username or chatroom mode.
|
||||||
client_states = {}
|
client_states = {}
|
||||||
|
# Add a dictionary to store user-specific paths
|
||||||
|
user_paths = {}
|
||||||
# let the user know the server is listening on port CHATPORT.
|
# let the user know the server is listening on port CHATPORT.
|
||||||
print(f"Chatserver listening on port: {CHATPORT}")
|
print(f"Chatserver listening on port: {CHATPORT}")
|
||||||
|
|
||||||
|
|
@ -50,6 +65,7 @@ def main():
|
||||||
client_socket.send(b"\nUse '%!' to exit, or '%?' for help.\n")
|
client_socket.send(b"\nUse '%!' to exit, or '%?' for help.\n")
|
||||||
client_socket.send(b"\nType in a username: ")
|
client_socket.send(b"\nType in a username: ")
|
||||||
client_states[client_socket] = "WAITING_FOR_USERNAME"
|
client_states[client_socket] = "WAITING_FOR_USERNAME"
|
||||||
|
user_paths[client_socket] = None # Initialize path for new client
|
||||||
# otherwise the socket is a client socket.
|
# otherwise the socket is a client socket.
|
||||||
else:
|
else:
|
||||||
# try to receive the message from the client
|
# try to receive the message from the client
|
||||||
|
|
@ -62,6 +78,7 @@ def main():
|
||||||
chat_rooms[sock] = "default"
|
chat_rooms[sock] = "default"
|
||||||
sock.send(b"\nUsername accepted. You are now in the 'default' chatroom.")
|
sock.send(b"\nUsername accepted. You are now in the 'default' chatroom.")
|
||||||
client_states[sock] = "NORMAL"
|
client_states[sock] = "NORMAL"
|
||||||
|
user_paths[sock] = None # Initialize path for the user
|
||||||
elif state == "WAITING_FOR_NEW_USERNAME":
|
elif state == "WAITING_FOR_NEW_USERNAME":
|
||||||
usernames[sock] = message.strip()
|
usernames[sock] = message.strip()
|
||||||
sock.send(b"\nUsername changed successfully.")
|
sock.send(b"\nUsername changed successfully.")
|
||||||
|
|
@ -75,8 +92,82 @@ def main():
|
||||||
if old_chatroom != "default" and old_chatroom not in chat_rooms.values():
|
if old_chatroom != "default" and old_chatroom not in chat_rooms.values():
|
||||||
print(f"\nChatroom '{old_chatroom}' is empty and removed.")
|
print(f"\nChatroom '{old_chatroom}' is empty and removed.")
|
||||||
client_states[sock] = "NORMAL"
|
client_states[sock] = "NORMAL"
|
||||||
else:
|
elif state == "NORMAL":
|
||||||
if message.strip() == "%!":
|
if message.startswith("@") and "-ls" in message:
|
||||||
|
# Parse the message format: @RECEIVING_USERNAME@SENDING_USERNAME -ls
|
||||||
|
parts = message.split()
|
||||||
|
if len(parts) >= 2 and "-ls" in parts[1]:
|
||||||
|
usernames_part = parts[0]
|
||||||
|
if usernames_part.count("@") == 2:
|
||||||
|
receiving_username, sending_username = usernames_part[1:].split("@")
|
||||||
|
# Find the receiving user's socket
|
||||||
|
receiving_sock = next(
|
||||||
|
(s for s, u in usernames.items() if u == receiving_username), None
|
||||||
|
)
|
||||||
|
sending_sock = next(
|
||||||
|
(s for s, u in usernames.items() if u == sending_username), None
|
||||||
|
)
|
||||||
|
if receiving_sock and sending_sock:
|
||||||
|
user_path = user_paths.get(receiving_sock)
|
||||||
|
if user_path and os.path.isdir(user_path):
|
||||||
|
# List files in the receiving user's directory
|
||||||
|
files = os.listdir(user_path)
|
||||||
|
if files:
|
||||||
|
file_list = "\n".join(
|
||||||
|
[format_file_info(os.path.join(user_path, f)) for f in files]
|
||||||
|
)
|
||||||
|
sending_sock.send(
|
||||||
|
f"Files in {receiving_username}'s directory:\n{file_list}".encode('utf-8')
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sending_sock.send(
|
||||||
|
f"No files in {receiving_username}'s directory.".encode('utf-8')
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sending_sock.send(
|
||||||
|
f"Error: {receiving_username} has no valid directory set.".encode('utf-8')
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
sock.send(b"Error: One or both users not found.")
|
||||||
|
else:
|
||||||
|
sock.send(b"Error: Invalid message format.")
|
||||||
|
elif message.startswith("@") and "-f" in message:
|
||||||
|
# Parse the message format: @RECEIVING_USERNAME@SENDING_USERNAME -f FILENAME
|
||||||
|
parts = message.split()
|
||||||
|
if len(parts) >= 3 and "-f" in parts[1]:
|
||||||
|
usernames_part = parts[0]
|
||||||
|
if usernames_part.count("@") == 2:
|
||||||
|
receiving_username, sending_username = usernames_part[1:].split("@")
|
||||||
|
# Find the receiving user's socket
|
||||||
|
receiving_sock = next(
|
||||||
|
(s for s, u in usernames.items() if u == receiving_username), None
|
||||||
|
)
|
||||||
|
sending_sock = next(
|
||||||
|
(s for s, u in usernames.items() if u == sending_username), None
|
||||||
|
)
|
||||||
|
if receiving_sock and sending_sock:
|
||||||
|
if len(parts) == 3:
|
||||||
|
# File request: @RECEIVING_USERNAME@SENDING_USERNAME -f FILENAME
|
||||||
|
filename = parts[2]
|
||||||
|
receiving_sock.send(
|
||||||
|
f"FILE_REQUEST {sending_username} {filename}".encode('utf-8')
|
||||||
|
)
|
||||||
|
elif len(parts) > 5 and parts[-1] == "ENDFILE":
|
||||||
|
# File transfer: @RECEIVING_USERNAME@SENDING_USERNAME -f FILENAME FILETYPE FILELENGTH FILEBYTES ENDFILE
|
||||||
|
filename = parts[2]
|
||||||
|
filetype = parts[3]
|
||||||
|
filelength = int(parts[4])
|
||||||
|
filebytes = " ".join(parts[5:-1]).encode('utf-8')
|
||||||
|
receiving_sock.send(
|
||||||
|
f"FILE_TRANSFER {sending_username} {filename} {filetype} {filelength}".encode('utf-8')
|
||||||
|
)
|
||||||
|
receiving_sock.send(filebytes)
|
||||||
|
receiving_sock.send(b"ENDFILE")
|
||||||
|
else:
|
||||||
|
sock.send(b"Error: One or both users not found.")
|
||||||
|
else:
|
||||||
|
sock.send(b"Error: Invalid message format.")
|
||||||
|
elif message.strip() == "%!":
|
||||||
sock.close()
|
sock.close()
|
||||||
socket_list.remove(sock)
|
socket_list.remove(sock)
|
||||||
del usernames[sock]
|
del usernames[sock]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue