I'm trying to create a multiuser chat interface in Python3 using tkinter. I am running into the error EOFError: Ran out of input with pickle data. Has anyone run into a similar error or has an idea of how to fix the problem? I have tried to increase bit number with no result.
The code uses four scrips which I have attached below. The server runs in the background while the client script is run twice on parallel run.
chat_server.py
import socket
from _thread import *
from ipv4 import get_ipv4
import pickle
from chat_main import Chat
server = get_ipv4()
port = 5555
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.bind((server, port))
except socket.error as e:
print(e)
s.listen(2)
print("Waiting for connection, server started")
connected = set()
rooms = {} # track id to object defined by class Main
id_count = 0 # how many people connected to server
HEADERSIZE = 10
def threaded_client(connection, u, room_id):
"""
:param connection:
:param u: [0, 1] --> user number
:param room_id:
:return:
"""
global id_count
connection.send(str.encode(str(u))) # send starting data --> 0 or 1 (user number)
while True:
"""
reset: update no new information from other user
get: client sends text, update server, send any updates from other user back to client"
"""
try:
data = connection.recv(2048*2).decode() # pull any ready info from server
if room_id in rooms:
room = rooms[room_id] # make sure room is still there
if not data: # if no data to read, break
break
else:
if data == "reset1": # reset that user one went
room.reset_sent(0)
elif data == "reset2": # reset that user two went
room.reset_sent(1)
elif data != "get": # get the room from server
room.send(u, data)
connection.sendall(pickle.dumps(room)) # send the updated room object back to server
else:
break
except Exception as e:
print(f"Error {e}")
break
print("Lost connection")
try:
del rooms[room_id]
print(f"Room {room_id} terminated")
except:
pass
id_count -= 1
connection.close()
while True:
conn, addr = s.accept() # --> accepts incoming connection and address
print(f"Connected to {addr}") # lets user know the connection was sucessful
id_count += 1 # user count += 1
user_id = (id_count - 1)//2 # create unique game code based on number of users
if id_count % 2 == 1:
u = 0 # user 1
# create a new game
rooms[user_id] = Chat(user_id) # id = game
print("Creating a new game...")
else:
u = 1 # user two
rooms[user_id].ready = True # ready to launch chat!
start_new_thread(threaded_client, (conn, u, user_id)) # start thread
chat_client.py
import tkinter as tk
from chat_network import Network
def tk_main(data, net):
window = tk.Tk()
window.update()
window.title("Room")
window.update()
window.geometry("500x500")
window.update()
window.resizable(True, True)
window.update()
data = data
data_str = ""
for item in data:
data_str += f"{item}\n\n"
window.update()
main_frame = tk.LabelFrame(window, text="Welcome to Dollartree Discord - HAVE FUN!")
window.update()
main_frame.pack(fill="both", expand="yes", padx=10, pady=10)
window.update()
chat_frame = tk.Frame(master=main_frame, bg="#d1d1d1")
window.update()
chat_frame.pack(expand="yes", fill="both", padx=5, pady=5)
window.update()
scroll = tk.Scrollbar(master=chat_frame)
window.update()
scroll.grid(sticky="nws", column=1, row=0, padx=0, pady=5)
window.update()
listbox = tk.Listbox(master=chat_frame, yscrollcommand=scroll.set)
window.update()
listbox.grid(column=0, row=0, sticky="nsew", padx=5, pady=5)
window.update()
for item in data:
listbox.see(tk.END)
listbox.insert(tk.END, item)
window.update()
scroll.config(command=listbox.yview)
window.update()
input_frame = tk.Frame(master=chat_frame, bg="#d1d1d1")
window.update()
text_input = tk.Entry(master=input_frame)
window.update()
button = tk.Button(master=input_frame, text="Send Message", command=lambda: send(text_input, window, listbox, scroll, data, net))
window.update()
text_input.grid(row=1, column=0, sticky="ew", padx=5, pady=5)
window.update()
button.grid(column=1, row=1, sticky="w", padx=5, pady=5)
window.update()
input_frame.grid(row=1, sticky="nwe")
window.update()
chat_frame.columnconfigure(tuple(range(1)), weight=2)
window.update()
chat_frame.rowconfigure(tuple(range(1)), weight=2)
window.update()
input_frame.columnconfigure(tuple(range(1)), weight=2)
window.update()
input_frame.rowconfigure(tuple(range(1)), weight=2)
window.update()
return window, listbox
def send(text_input, window, listbox, scroll, data, net):
if (text_input.get()).strip() != "":
message = text_input.get()
window.update()
data.append(message)
window.update()
text_input.delete(0, "end")
window.update()
listbox.insert("end", message)
window.update()
net.send_old(message)
if not scroll.get()[1] < 1:
listbox.see(tk.END)
window.update()
def main():
run = True
n = Network()
user = int(n.get_user())
print("You have entered the chat room.")
print(f"You are user {user}.")
t, l = tk_main(["You have entered the chat", f"You are user {user}"], n)
t.update()
try:
while run:
try:
room = n.send_old("get")
except Exception as e:
print(f"Could not get room, error: {e}")
break
t.update()
if user == 0 and room.u2_went():
l.insert(room.get_user_text(1))
t.update()
n.send_old("reset2")
t.update()
elif user == 1 and room.u1_went():
l.insert(room.get_user_text(1))
t.update()
n.send_old("reset1")
t.update()
except Exception as e:
print(f"Error: {e}")
main()
chat_network.py
import socket
from ipv4 import get_ipv4
import pickle
class Network:
def __init__(self):
self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # don't understand line
self.server = get_ipv4()
self.port = 5555
self.addr = (self.server, self.port) # don't understand line
self.u = self.connect()
def get_user(self):
"""
:return: user
"""
return self.u
def connect(self):
"""
:return: [0, 1] user number
"""
try:
self.client.connect(self.addr)
return self.client.recv(2048).decode()
except:
pass
def send_old(self, data):
"""
:param data: text message
:return: any updates to room object
"""
try:
self.client.send(str.encode(data)) # send data over server
return pickle.loads(self.client.recv(2048*2)) # get any data from server in object form, load with pickle
except socket.error as e:
print(e)
chat_main.py
class Chat:
def __init__(self, room_id):
"""
:param room_id: code to get into specified room
"""
self.user1_went = False
self.user2_went = False
self.ready = False
self.id = room_id
self.texts = [[["past"], None], [["past"], None]]
def get_user_text(self, user):
"""
:param user: [0, 1] user number
:return: user text
"""
return self.texts[user][1]
def send(self, user, text):
"""
:param user: [0, 1]
:param text: string, text sent
:return: no return value
"""
self.texts[user][-1] = text
if user == 0:
self.user1_went = True
else:
self.user2_went = True
def connected(self):
"""
:return: True or False --> make sure both users are connected to server
"""
return self.ready
def u1_went(self):
return self.user1_went
def u2_went(self):
return self.user2_went
def sent(self, user, text):
"""
:param user: [0, 1] user number
:param text: text input
:return: none, update user text in texts list
"""
self.texts[user][0].append(text)
self.texts[user][-1] = None
def reset_sent(self, user):
"""
:param user: [0, 1]
:return: no return value
"""
if user == 0:
self.user1_went = False
if self.texts[user][1] is not None:
self.texts[user][0].append(str(self.texts[user][1]))
self.texts[user][1] = None
else:
self.user2_went = False
if self.texts[user][1] is not None:
self.texts[user][0].append(str(self.texts[user][1]))
self.texts[user][1] = None