I have a server and a client and they can connect to each other and I can send from the client to the server but not vice versa. The program fails when i'm trying to send back data to the client.
client.py
from tkinter import *
import socket
import threading
tLock = threading.Lock()
shutdown = False
host = '::1';
port = 5000;
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
class Application(Frame):
def __init__(self, master=None):
#Create master frame
Frame.__init__(self,master)
self.grid()
self.master.title("Test 1")
self.conn=False #State of connection to server
#Configure main frame
for r in range (4):
self.master.rowconfigure(r, weight=1)
for c in range (2):
self.master.columnconfigure(c)
#Create sub frames
TopFrame=Frame(master)
TopFrame.grid(row=0, column=0, rowspan=3)
BottomFrame=Frame(master, bg="green")
BottomFrame.grid(row=4, column=0, rowspan=3)
SideFrame=Frame(master, bg="red")
SideFrame.grid(column=1, row=0, rowspan=4)
#Create Chat log
self.chatlog=Text(TopFrame)
self.chatlog.pack(padx=5, pady=5)
#messenger and send button
self.e1=Entry(BottomFrame, width=92)
self.e1.pack(side=LEFT, pady=5, padx=5)
sendButton=Button(BottomFrame, text="Send", command=self.sendmessage, height = 1, width = 10)
sendButton.pack(side=LEFT)
#Create connect disconnect buttons
b1=Button(SideFrame, text="Connect", command=self.connect)
b1.grid(row=0, column=0, padx=5, pady=5)
b2=Button(SideFrame, text="Disconnect", command=self.disconnect)
b2.grid(row=1, column=0, padx=5, pady=5)
def connect(self): #Connect to server
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===ATTEMPTING TO CONNECT TO SERVER\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
s.connect((host,port))
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, (s))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("\n\n PLEASE ENTER A USER NAME AND SEND"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
self.conn=True
print("Connected") #Connection successful
# M- Adding threading for receiving messages
rT = threading.Thread(target=self.receving, args=("RecvThread",s))
rT.start()
# When attempting to connect a second time, produces OS error: an operation was attempted on something that is not a socket
def disconnect(self):
if self.conn: #Tests to see if client is connected
s.close()
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===DISCONNECTED FROM SERVER.\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
self.conn=False
else: #Prevents attempting to disconnect when already disconnected
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===YOU AREN'T CURRENTLY CONNECTED.\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
def sendmessage(self):
if self.conn: #Prevents sending if not connected
self.msg=self.e1.get()
if self.msg == "": #Empty message catcher
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===YOU CANNOT SEND AN EMPTY MESSAGE.\n" ))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
else:
self.send_data(self.msg) #Sends message to the server
self.e1.delete(0, END)
else:
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===YOU ARE NOT CONNECTED TO A SERVER. YOU CANNOT SEND A MESSAGE.\n" ))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
# M- Method to handle receiving from the server
# adds the data to the chat log.
def receving(self, name, sock):
while not shutdown:
try:
tLock.acquire()
while True:
data, addr = sock.recvfrom(1024)
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, (data + '\n'))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
except:
pass
finally:
tLock.release()
def send_data(self, message):
try:
s.send(message.encode('UTF-8'))
except:
self.chatlog['state'] = NORMAL
self.chatlog.insert(END, ("===THE PREVIOUS MESSAGE DIDN'T SEND. THIS IS POSSIBLY DUE TO A SERVER ERROR.\n"))
self.chatlog['state'] = DISABLED
self.chatlog.yview(END)
root = Tk()
app = Application(root)
app.mainloop()
Server.py
import socket
import threading
import sys
hosts=["::1"]
port=5000
#dictionay to hold the socket as the key and the user name as the value
dic = {}
class Server:
def __init__ (self,hosts,port):
self.host=hosts
self.port=port
self.socketserver=socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
self.socketserver.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Socket has been created successfully")
for i in hosts:
try:
host=i
self.socketserver.bind((host,port))
print("Connection succeded to address",i)
print ("The server is now binded to the following IP address",host,"Port",port)
break
except socket.error:
print("Connection failed to address",i)
else:
sys.exit()
def Accept_connections(self):
while True:
self.socketserver.listen(10)
print("Socket is now awaiting connections")
server, clientaddress = self.socketserver.accept()
print("Connection enstablished with: " +str(clientaddress))
threading.Thread(target = self.message,args = (server,clientaddress),).start()
def message(self,server,clientaddress):
while True:
try:
data= server.recv(1024)
print("data ", data)
#check to see if it is a new socket that is not in the stored
#socket dictionary
if server not in dic.keys():
print("if statement")
#if it is a new socket
#add the socket and the user name
dic[server] = data
for key in dic:
#send the joined message to the users
print("failing")
key.send("\n\n" + data + " has joined the chat")
else:
#alias is a variable used to store the sockets username
alias = dic[server]
for key in dic:
#send the message to the sockets in the dictionary
key.send(alias + ": " +data)
except:
server.close()
#edit this bit !
print("Data transfer failed")
return False
Server(hosts,port).Accept_connections()
The program fails at:
key.send("\n\n" + data + " has joined the chat")
When a client connects they enter a user name to be known as. This stores it with a socket in a dictionary. The error occurs when looping round the sockets to inform the other clients they have joined. Any help would be brilliant. This was working on python27 but has now stopped when i updated to python34.
Managed to find the fix. When I upgraded to 3 the sending stopped working as it was trying to send strings. Python 3 requires bytes to be sent.
key.send(data + b' joined')
Was the solution
Related
I developed a simple chat app that allows users to connect to a server and chat. This is the code for the server.
import os
from datetime import datetime
def log_file_name():
n = str(datetime.now())
m = n.replace(':','_').replace(' ','---')
l = m.split('.')[0]
l = f'{l}.txt'
return l
HOST = '127.0.0.1'
PORT = 10001
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#print(type(server_socket))
server.bind((HOST, PORT))
server.listen()
print('server_initiated...')
logfile = os.path.join('logs', log_file_name())
with open(logfile, 'w') as fh:
fh.write(f'{str(datetime.now())} log file initiated!\n\n')
clients = []
nicknames = []
#broadcast
def broadcast(message):
#print(clients)
for client in clients:
client.send(message)
def handle(client):
while True:
try:
message = client.recv(1024)
#print(f'{nicknames[clients.index(client)]} says {message}')
broadcast(message)
with open(logfile, 'a') as fh:
fh.write(f"{nicknames[clients.index(client)]} says {message.decode('utf-8')}\n")
except Exception:
index = clients.index(client)
clients.remove(client)
client.close()
left_nick = nicknames[index]
leaving_notes = f"{left_nick} just left the chat!! -- time {str(datetime.now()).split(' ')[1].split('.')[0]}"
broadcast(leaving_notes.encode('utf-8'))
with open(logfile,'a') as fh:
fh.write(f'{leaving_notes}\n')
nicknames.remove(left_nick)
break
#recieve message
def recieve():
while True:
client, address = server.accept()
#print(dir(client))
#print(client._io_refs)
#print(f'Connected with {str(address)}!!')
with open(logfile, 'a') as fh:
fh.write(f'Connected with {str(address)}!!\n')
client.send('Nickname'.encode('utf-8'))
nickname = client.recv(512).decode('utf-8')
nicknames.append(nickname)
clients.append(client)
#print(f'from 1st step clients are {clients}')
#print(f'Nickname of the client is {nickname}')
with open(logfile, 'a') as fh:
fh.write(f'Nickname of the client is {nickname}\n')
broadcast(f'Notice from server!! {nickname} just connected to the server!\n'.encode('utf-8'))
client.send(f'Connected to the server as {nickname}\n'.encode('utf-8'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
recieve()
Then I exposed that port to public using ngrok (ngrok http 10001), and it generated a public ip for me.
I coded a simple client gui using tkinter and I tried to connect the socket in to to above ngrok server I got. But I cannot broadcast messages. When I try to broadcast a message the GUI automatically closes. The reason is it meets a ConnectionAbortError.
Code for client-
import threading
import tkinter
import socket
import tkinter.simpledialog
import tkinter.scrolledtext
import os
#HOST = socket.gethostbyname(socket.gethostname())
#PORT = 10001
HOST = '3a7d-2402-4000-1245-cd8a-5d64-9c3f-25a3-79a4.in.ngrok.io'
PORT = 443 #or 80
class Client:
def __init__(self,host,port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))
msg = tkinter.Tk()
msg.withdraw()
self.nickname = tkinter.simpledialog.askstring('Nickname', 'Please enter a nickname', parent=msg)
self.gui_done = False
self.running = True
gui_t=threading.Thread(target=self.gui_loop)
recieve_t=threading.Thread(target=self.recieve)
gui_t.start()
recieve_t.start()
def gui_loop(self):
self.win = tkinter.Tk()
self.win.configure(bg='lightgray')
self.chat_label = tkinter.Label(self.win, text='Chat:', bg='lightgray')
self.chat_label.config(font=('Arial',12))
self.chat_label.pack(padx=20, pady=5)
self.text_area = tkinter.scrolledtext.ScrolledText(self.win)
self.text_area.pack(padx=20,pady=5)
#self.text_area.config(state='disabled')
self.msg_label = tkinter.Label(self.win, text='Message:', bg='lightgray')
self.msg_label.config(font=('Arial', 12))
self.msg_label.pack(padx=20, pady=5)
self.input_area = tkinter.Text(self.win, height=3)
self.input_area.pack(padx=20, pady=5)
self.send_button = tkinter.Button(self.win, text='Send', command=self.write)
self.send_button.config(font=('Arial', 12))
self.send_button.pack(padx=20, pady=5)
self.gui_done = True
self.win.protocol('WM_DELETE_WINDOW', self.stop)
self.win.mainloop()
def write(self):
message = f"{self.nickname}: {self.input_area.get('1.0', 'end')}"
#print(message)
self.sock.send(message.encode('utf-8'))
self.input_area.delete('1.0','end')
def recieve(self):
while self.running:
try:
message = self.sock.recv(1024).decode('utf-8')
print(message)
if message == 'Nickname':
self.sock.send(self.nickname.encode('utf-8'))
else:
if self.gui_done:
#print('I hit here often')
self.text_area.config(state='normal')
self.text_area.insert('end', message)
self.text_area.yview('end')
#self.text_area.config(status='disabled') #never use this inside a loop, disabled blocks the code....
except ConnectionAbortedError: #when closed the window I come here..
print('Am i here?')
#break
os._exit(0)
#break
except:
break
print('Error')
self.sock.close()
break
def stop(self):
self.running = False
self.win.destroy()
self.sock.close()
exit(0)
client = Client(HOST, PORT)
If you run this please make sure to create a directory called logs to save the log of communication. Or else it will give an error(You can try it on localhost). I think I am doing something that doesn't work here. Can you point it out to me? or can you give me an alternative way of doing it?
from tkinter import *
import _thread
from typing import TextIO
#页面代码
root = Tk()
root.title('TPC服务端')
root.geometry('640x480')
label_1 = Label(root,relief=GROOVE,text='从客户端接收的数据')
label_1.place(relx=0.1,rely=0.0,relwidth=0.4,relheight=0.1)
Operate = Text(root,relief=GROOVE)
Operate.place(relx=0.1,rely=0.1,relwidth=0.4,relheight=0.4)
Tips = Text(root,relief=GROOVE)
Tips.place(relx=0.1,rely=0.5,relwidth=0.4,relheight=0.4)
Tips.insert(END,'当前状态:\n')
Tips.configure(state=DISABLED)
root.mainloop()
class TCPServer():
def __init__(self):
self.HOST = '192.0.0.1'
self.PORT = 8080
self.BUFSIZ = 1024
self.ADDRESS = (self.HOST,self.PORT)
self.tcpServerSocket = socket(AF_INET, SOCK_STREAM)
self.tcpServerSocket.bind(self.ADDRESS) #IP地址和固定端口信息
self.tcpServerSocket.listen(5)
def try_connect(self):
global var
var='服务器正在运行,等待客户端连接...\n'
Tips.insert(END,var)
Tips.configure(state=DISABLED)
while True:
var='服务器正在运行,等待客户端连接...\n'
Tips.configure(state=NORMAL)
Tips.insert(END,var)
Tips.configure(state=DISABLED)
self.client_socket, self.client_address = self.tcpServerSocket.accept()
var='客户端{}已连接!\n'.format(self.client_address)
Tips.configure(state=NORMAL)
Tips.insert(END,var)
Tips.configure(state=DISABLED)
while True:
self.data = self.client_socket.recv(self.BUFSIZ)
if(self.data):
var='接收到消息 {}({} bytes) 来自 {}\n'.format(self.data.decode('utf-8'), len(self.data), self.client_address)
# 返回响应数据,接受的数据不做处理即返回
self.client_socket.send(self.data)
var='发送消息 {} 至 {}\n'.format(self.data.decode('utf-8'), self.client_address)
Tips.configure(state=NORMAL)
Tips.insert(END,var)
Tips.configure(state=DISABLED)
Operate.configure(state=NORMAL)
Operate.insert(END,self.data)
Operate.configure(state=DISABLED)
else:
var='客户端 {} 已断开!\n'.format(self.client_address)
Tips.configure(state=NORMAL)
Tips.insert(END,var)
Tips.configure(state=DISABLED)
break
# 关闭socket
self.client_socket.close()
# 取消监听socket,自此拒绝响应其它客户端
self.tcpServerSocket.close()
Server = TCPServer()
_thread.start_new_thread(Server.try_connect)
root.mainloop()
![text](enter image description here
I want to know why such a mistake happened.I am using python to make a simple network communication program.It contains both the client and server sides.This is my client program code.
I am a beginner.
The server connects to the client .i use vscode to write the code.I use python 3.10
I Was working a tcp chat room and when i run it it shows nicknames and who joined but the message doesnt go through and after trying to send a message the 4th time it show the error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\f\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
return self.func(*args)
File "besthost.py", line 59, in write
self.sock.send(message.encode('utf-8'))
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
The host file is
import socket
import threading
import tkinter
import tkinter.scrolledtext
from tkinter import simpledialog
HOST = '127.0.0.1'
PORT = 9091
class Client:
def __init__(self, host, port):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((host, port))
msg = tkinter.Tk()
msg.withdraw()
self.nickname = simpledialog.askstring("nickname", "please choose a nickname", parent=msg)
self.gui_done = False
self.running = True
gui_thread = threading.Thread(target=self.gui_loop)
receive_thread = threading.Thread(target=self.receive)
gui_thread.start()
receive_thread.start()
def gui_loop(self):
self.win = tkinter.Tk()
self.win.configure(bg="darkolivegreen")
self.chat_label = tkinter.Label(self.win, text="chat", bg="lightgray")
self.chat_label.config(font=("arial", 12))
self.chat_label.pack(padx=20, pady=5)
self.text_area = tkinter.scrolledtext.ScrolledText(self.win)
self.text_area.pack(padx=20, pady=5)
self.text_area.config(state='disabled')
self.msg_label = tkinter.Label(self.win, text="message", bg="lightgray")
self.msg_label.config(font=("arial", 12))
self.msg_label.pack(padx=20, pady=5)
self.input_area = tkinter.Text(self.win, height =3)
self.input_area.pack(padx=20,pady=5)
self.send_button = tkinter.Button(self.win, text="send", command=self.write)
self.send_button.config(font=("arial", 12))
self.send_button.pack(padx=20, pady=5)
self.gui_done = True
self.win.protocol("WM_DELETE_WINDOW", self.stop)
self.win.mainloop()
def write(self):
message = f"{self.nickname}:{self.input_area.get('1.0', 'end')}"
self.sock.send(message.encode('utf-8'))
self.input_area.delete('1.0', 'end')
def stop(self):
self.running = False
self.win.destroy()
self.sock.close()
exit(0)
def receive(self):
while self.running:
try:
message = self.sock.recv(1024).decode('utf-8')
if message=='NICK':
self.sock.send(self.nickname.encode('utf-8'))
else:
if self.gui_done:
self.text_area.config(state='normal')
self.text_area.insert('end', message)
self.text_area.yview('end')
self.text_area.config(state='disabled')
except ConnectionAbortedError:
break
except:
print("error")
self.sock.close()
break
client = Client(HOST, PORT)
The server file is
import socket
import threading
HOST = '127.0.0.1'
PORT = 9091
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()
clients = []
nicknames = []
def broadcast(message):
for client in clients:
client.send(message)
def handle(client):
while True:
try:
message = client.recv(1024).decode('utf-8')
print(f"{nicknames[client.index(client)]})")
broadcast(message)
except:
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
nicknames.remove(nickname)
break
def receive():
while True:
client, address = server.accept()
print(f"connected with {str(address)}!")
client.send("NICK".encode('utf-8'))
nickname = client.recv(1024)
nicknames.append(nickname)
clients.append(client)
print(f"nicknames of client is {nickname}")
broadcast(f"{nickname} connected successfully!\n".encode('utf-8'))
client.send("connected to the server".encode('utf-8'))
thread = threading.Thread(target=handle, args=(client,))
thread.start()
print("server running")
receive()
I tried searching but i didnt see anyone with this issue and i dont think there are any programming errors
If anyone has an idea whats wrong please let me know .
Thanks
Your the biggest mistake is except: without printing information about problem.
I use
except Exception as ex:
print (ex)
# ... rest ...
and first it shows me
'socket' object has no attribute 'index'
because you forgot s in word clients in line
print(f"{nicknames[clients.index(client)]})")
Next it shows me
a bytes-like object is required, not 'str'
because you send str instead of bytes in next line - and you need encode()
broadcast(message.encode('utf-8'))
After these changes it start working for me.
def handle(client):
while True:
try:
message = client.recv(1024).decode('utf-8') # convert bytes to string
print(f"{nicknames[clients.index(client)]})") # forgot `s`
broadcast(message.encode('utf-8')) # convert string back to bytes
except Exception as ex:
print('Exception:', ex)
index = clients.index(client)
clients.remove(client)
client.close()
nickname = nicknames[index]
nicknames.remove(nickname)
break
I have a client that refreshes with the server every 10 seconds. When the client checks in with the server. I would like the server to send label text values back to the client to be applied to client labels.
The client sends a serial key and once the server verifies it. the server sends back a message to the client. I have a itemPrice to be used as a label text being sent in that same action before the connection breaks. I have no idea how to retrieve the itemPrice on the client side. Is there a way of tagging the value to be used for a client variable?
The server will be holding the text for client labels. How can i send this text to be a variable on the client?
Client.py
from tkinter import *
import socket
root = Tk()
# Variables
itemPrice1 = ''
itemPrice2 = ''
# SERVER CONNECTION
serialNumber = '001'
# Define Refresh Time
def Refresh():
root.after(10000, Refresh) # every 10 seconds...
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 10000)
sock.connect(server_address)
sock.send(serialNumber.encode('UTF-8'))
amount_received = 0
data = sock.recv(16)
amount_received += len(data)
print('received "%s"' % data)
# Layout
root.config(background='black')
item1 = Label(root, text=itemPrice1)
item1.grid(row=0, column=0)
item1.config(background='grey', width=10)
closeButton = Button(root, text='Close', command=root.destroy)
closeButton.grid(row=1, column=0)
Refresh()
root.mainloop()
Server.py
import socket
import data
import price
# VARIABLES
itemPrice1 = price.itemPrice1
# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Bind the socket to the port
server_address = ('localhost', 10000)
print('starting up on %s port %s' % server_address)
sock.bind(server_address)
# Listen for incoming connections
sock.listen(1)
while True:
# Wait for a connection
print('waiting for a connection')
connection, client_address = sock.accept()
try:
print('connection from', client_address)
# Receive the data in small chunks and retransmit it
while True:
dataRec = connection.recv(16)
print(client_address, dataRec)
if dataRec == data.serialNumber:
print('sending data back to the client')
connection.send('Serial Valid'.encode('UTF-8'))
connection.send(itemPrice1)
break
else:
connection.send('Key Not Valid'.encode('UTF-8'))
break
finally:
# Clean up the connection
connection.close()
Price.py
itemPrice1 = b'0.01'
Data.py
serialNumber = b'001'
For the server. I removed the variables and forward the prices directly from the price.py
if dataRec == data.serialNumber:
print('sending data back to the client')
connection.send('Serial Valid'.encode('UTF-8'))
connection.send(price.itemPrice1.encode('UTF-8')) # SENDING PRICE TO CLIENT FOR LABEL
connection.send(price.itemPrice2.encode('UTF-8'))
break
For the client. I placed the variables directly in the definition.
def Refresh():
root.after(10000, Refresh) # every 10 seconds...
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 10000)
sock.connect(server_address)
sock.send(serialNumber.encode('UTF-8'))
amount_received = 0
data = sock.recv(12)
amount_received += len(data)
print('received "%s"' % data)
itemPrice1 = sock.recv(4)
print('price', itemPrice1)
itemPrice1Label.config(text=itemPrice1)
itemPrice2 = sock.recv(4)
print('price', itemPrice2)
itemPrice2Label.config(text=itemPrice2)
Doing this I have to define the sock.recv() amount so the character count doesn't overlap with each other. Example being.
item price 1 = 1.05
item price 2 = 0.10
itemPrice1 = sock.recv(7)
would print 1.050.1
vs
itemPrice1 = sock.recv(4)
would print 1.05
So, I have a server completely written in Python 2.7:
from socket import *
from select import *
HOST = "127.0.0.1"
PORT = 1993
server = socket(AF_INET, SOCK_STREAM)
server.bind((HOST, PORT))
server.listen(5)
clients = []
def getClients():
to_use = []
for client in clients:
to_use.append(client[0])
return to_use
while(True):
read, write, error = select([server],[],[],0)
if(len(read)):
client, address = server.accept()
clients.append([client, address, []])
to_use = getClients()
try:
read, write,error = select(to_use,[],[],0)
if(len(read)):
for client in read:
data = client.recv(1024)
print(bytes.decode(data))
if(data == 0):
for c in clients:
if c[0] == client:
clients.remove(c)
break
else:
for c in clients:
c[2].append(data)
except:
pass
try:
to_use = getClients()
read, write, error = select([], to_use, [], 0)
if(len(write)):
for client in write:
for c in clients:
if c[0] == client:
for data in c[2]:
sent = client.send(data)
if(sent == len(data)):
c[2].remove(data)
break
except:
pass
What I need to do is get constant updates for data (messages) from the
server and print them to a text box made in Tkinter.
The receiving code:
from socket import *
from select import *
HOST = "127.0.0.1"
PORT = 1993
sock = socket(AF_INET, SOCK_STREAM)
sock.connect((HOST, PORT))
while True:
data = bytes.decode(sock.recv(1024))
print data
It doesn't have to be Tkinter, but that's what I have been trying in; as long as it uses a GUI. Don't worry about sending messages I just need to be able to receive the data and print it to the text box/area.
The basic framework is to first create all of the widgets. Next, write a function that reads the data and updates the UI. Finally, arrange to have this function called every few milliseconds.
Roughly speaking, it looks something like this:
import Tkinter as tk
...
class Example(object):
def __init__(self):
self.root = tk.Tk()
self.text = tk.Text(root)
self.text.pack(fill="both", expand=True)
...
def start(self):
self.read_periodically()
self.root.mainloop()
def read_periodically(self):
# read the data
data = bytes.decode(sock.recv(1024))
# update the UI
self.text.insert("end", data)
# cause this function to be called again in 100ms
self.after(100, self.read_periodically)
example = Example()
example.start()
If the data is not a steady stream which causes sock.recv(1024) to block, your UI will freeze while it's waiting for data. If that's the case, you can move the reading of the socket to a thread, and have the thread communicate with the GUI via a thread-safe queue.
If the data is in a steady stream, or you set up a non-blocking socket, you don't have to do any of that.
I wanted to submit a comment first, but give this a try:
You can use something other than a start button to get things going I just put it there for ease of use
from Tkinter import *
import threading
from socket import *
from select import *
master = Tk() #create the GUI window
#put the test program in a seperate thread so it doesn't lock up the GUI
def test_program_thread():
thread = threading.Thread(None, test_program, None, (), {})
thread.start()
def test_program():
HOST = "127.0.0.1"
PORT = 1993
sock = socket(AF_INET, SOCK_STREAM)
sock.connect((HOST, PORT))
while True:
data = bytes.decode(sock.recv(1024))
terminal_listbox.insert(END, str(data))
master.update() #I don't think this line is necessary, but put it here just in case
# set the gui window dimensions and the title on the GUI
master.minsize(width=450, height=450)
master.wm_title("Stack Problem")
# Start button is set to y and starts the test program when hit
start_button = Button(master, text='START', command=test_program_thread)
start_button.place(x=5, y=5)
# scroll bar for the terminal outputs
scrollbar = Scrollbar(master)
scrollbar.place(x=420, y=150)
# Terminal output. Auto scrolls to the bottom but also has the scroll bar incase you want to go back up
terminal_listbox = Listbox(master, width=65, height=13)
terminal_listbox.place(x=5, y=100)
terminal_listbox.see(END)
scrollbar.config(command=terminal_listbox.yview)
#GUI loops here
master.mainloop()