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 sys
|
||||
import select
|
||||
|
|
@ -15,6 +16,15 @@ def main():
|
|||
SERVER_HOST = sys.argv[1]
|
||||
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
|
||||
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
try:
|
||||
|
|
@ -22,6 +32,9 @@ def main():
|
|||
client_socket.connect((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:
|
||||
# use select to wait for either server messages or user input
|
||||
read_sockets, _, _ = select.select([client_socket, sys.stdin], [], [])
|
||||
|
|
@ -33,6 +46,33 @@ def main():
|
|||
if not server_message:
|
||||
print("Disconnected from server")
|
||||
return
|
||||
if server_message.startswith("FILE_REQUEST"):
|
||||
# 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:
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import os
|
||||
import socket
|
||||
import select
|
||||
|
||||
|
|
@ -5,6 +6,18 @@ CHATPORT = 8181
|
|||
BUFFER_SIZE = 1024
|
||||
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():
|
||||
# set the flag variable to true for infinite loop
|
||||
quitFlag = True
|
||||
|
|
@ -31,6 +44,8 @@ def main():
|
|||
# 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.
|
||||
client_states = {}
|
||||
# Add a dictionary to store user-specific paths
|
||||
user_paths = {}
|
||||
# let the user know the server is 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"\nType in a 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.
|
||||
else:
|
||||
# try to receive the message from the client
|
||||
|
|
@ -62,6 +78,7 @@ def main():
|
|||
chat_rooms[sock] = "default"
|
||||
sock.send(b"\nUsername accepted. You are now in the 'default' chatroom.")
|
||||
client_states[sock] = "NORMAL"
|
||||
user_paths[sock] = None # Initialize path for the user
|
||||
elif state == "WAITING_FOR_NEW_USERNAME":
|
||||
usernames[sock] = message.strip()
|
||||
sock.send(b"\nUsername changed successfully.")
|
||||
|
|
@ -75,8 +92,82 @@ def main():
|
|||
if old_chatroom != "default" and old_chatroom not in chat_rooms.values():
|
||||
print(f"\nChatroom '{old_chatroom}' is empty and removed.")
|
||||
client_states[sock] = "NORMAL"
|
||||
elif state == "NORMAL":
|
||||
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:
|
||||
if message.strip() == "%!":
|
||||
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()
|
||||
socket_list.remove(sock)
|
||||
del usernames[sock]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue