Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 122 additions & 9 deletions Client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,136 @@
import threading
from tkinter import *
from tkinter import filedialog

SIZE = 1024
FORMAT = "utf-8"
PORT = 4000
DISCONNECT_MESSAGE = "!Disconnect!"

from performance_config import (
BUFFER_SIZE, FORMAT, PORT, DISCONNECT_MESSAGE,
optimize_socket
)

def connectToServer(IP):
"""Connect to server with optimized socket settings and better error handling"""
ADDR = (IP, PORT)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
# Apply socket optimizations before connecting
optimize_socket(sock)

# Set connection timeout
sock.settimeout(10) # 10 second connection timeout

sock.connect(ADDR)
print("Connect")
print(f"Connected to server at {IP}")

# Remove timeout after successful connection for normal operation
sock.settimeout(None)

return sock

except socket.timeout:
print("Connection timed out")
sock.close()
return None
except socket.gaierror:
print("Invalid IP address or hostname resolution failed")
sock.close()
return None
except ConnectionRefusedError:
print("Connection refused - server may not be running")
sock.close()
return None
except Exception as e:
print(e)
print("Failed to connect to server")
print(f"Failed to connect to server: {e}")
sock.close()
return None


def send_data_reliable(sock, data):
"""Send data reliably with error handling"""
try:
if isinstance(data, str):
data = data.encode(FORMAT)

total_sent = 0
while total_sent < len(data):
sent = sock.send(data[total_sent:])
if sent == 0:
raise RuntimeError("Socket connection broken")
total_sent += sent
return True
except Exception as e:
print(f"Error sending data: {e}")
return False


def receive_data_reliable(sock, size):
"""Receive data reliably with error handling"""
try:
data = b''
while len(data) < size:
chunk = sock.recv(size - len(data))
if not chunk:
break
data += chunk
return data
except Exception as e:
print(f"Error receiving data: {e}")
return b''


def check_connection(sock):
"""Check if socket connection is still alive"""
try:
# Send a small test message
sock.send(b'\x00')
return True
except:
return False


class ConnectionManager:
"""Manages multiple connections with connection pooling"""

def __init__(self):
self.connections = {}
self.lock = threading.Lock()

def get_connection(self, ip):
"""Get or create a connection to the specified IP"""
with self.lock:
if ip in self.connections:
conn = self.connections[ip]
if check_connection(conn):
return conn
else:
# Connection is dead, remove it
del self.connections[ip]

# Create new connection
conn = connectToServer(ip)
if conn:
self.connections[ip] = conn
return conn

def close_connection(self, ip):
"""Close connection to specified IP"""
with self.lock:
if ip in self.connections:
try:
self.connections[ip].close()
except:
pass
del self.connections[ip]

def close_all_connections(self):
"""Close all connections"""
with self.lock:
for conn in self.connections.values():
try:
conn.close()
except:
pass
self.connections.clear()


# Global connection manager instance
connection_manager = ConnectionManager()
Loading