Hey guys, I got a little bored and thought I would to make some of the basic Client/Server applications I have a little bit flashier with a gui interface. So far I have just been working with the server and the main problem that I run into is when the program has to enter a loop while waiting for a response the gui starts to hang. The work around I have been using so far which quite frankly sucks, is to print a response while the exeption is being raised. It keeps the gui from hanging but it's quite annoying. The other thing I tried was to have it sleep for a short period of time but the gui seems to really hate that. Is there a more common or better way to handle this? Here is the code I'm working with at the moment, sorry I do relize it's pretty sloppy right now. I promise to clean it up a bit once I can get it functioning a little better :).

from tkinter import *
from threading import Thread
from time import sleep
import socket

class Gui():
    def __init__(self, master):

        self.running = 0    #not listening
        self.addr = ""
        self.conn = ""
        
        self.frame = Frame(master)
        self.frame.pack(side = LEFT, anchor = N)

        self.startb = Button(self.frame, text = "Start", command = self.startc)
        self.startb.pack(side = LEFT, anchor = N)

        self.stopb = Button(self.frame, text = "Stop", command = self.stopc)
        self.stopb.pack(side = LEFT, anchor = N)

        self.connectionl = Label(self.frame, text = "not connected")
        self.connectionl.pack(side = LEFT, anchor = SW)

        
    def startc(self):
        if self.running == 0:
            self.running += 1
            self.ls = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            port = 9999
            self.ls.bind(('', port))
            print("Server listening on port %s" %port)
            self.ls.listen(1)
            self.ls.settimeout(.05)
            while self.running != 0:
                try:
                    (self.conn, self.addr) = self.ls.accept()
                    print("client is at", self.addr[0], "on port", self.addr[1])
                    self.running = 0
                except:
                    print("attempting to connect")#hangs without this
            if self.conn != "":
                self.rc = ""
                while self.rc != "done":
                    try:
                        self.rc = self.conn.recv(100).decode('utf-8')
                        print("got command", self.rc)
                    except:
                        sleep(.05)
                        print("no info sent yet")#hangs without this
                self.conn.close()
        else:
            self.running = 0
            print("Server not listening")

    def stopc(self):
        self.running = 0






root = Tk()
gui = Gui(root)
root.mainloop()

Recommended Answers

All 5 Replies

Don't know on TkIntering,
but if you're serious with your app, grab wxPython and MySQL-python. Make a client that will access remotely the mysql server, authenticate it and populate data/delete depending on whether they are admins or not

After that exercise, you will be fresh for a rest :)

It's still a valid problem 7 years later, and no solutions or comments!
I found it in a web search and when I ran it, it was not close to being correct. The threading model was imported but never used, though I'm sure it was intended to be. I started to make a comment that this should be removed from the system. Then I reconsidered, and took it on as a learning process to 'fix' it!

This has warts, but I believe it is close to the intent of the OP original:

#! /usr/bin/python
#
# It drove me a little crazy to be looking for socket-with-gui code and I came across this
# old question, with no corrections or answers.   It was pretty useless as it was, and I was
# going to suggest deleting it for bad information, so other people searching for help
# didn't have to deal with it.
#
# Then I reconsidered, because I saw what the original author was trying to do, so I took 
# his code, and added the threading, etc. to make it work (as a learning process for myself)
# (I tried to make all the print statements python2/python3 compatible)
# 
# I don't want to spend a lot of time prettying it up, that is an exercise for the reader.
# So caveat emptor, but there should be enough here for you to work with.
#
#---------------------------
#
# To watch it work start it running, the press the start button.
# It will tell you it is waiting.
#
# then the simplest test is to open a browser, and in the address box, type:
#
# http://localhost:9999/Here_Is_Some_Stuff.
#
# and you'll see it (All the headers and stuff) be received.  
#

from Tkinter import *   # use lower case tkinter for python3
from threading import Thread
from time import sleep,time
import socket

class Gui():
    def __init__(self, master):
        self.running = 0    #not listening
        self.addr = None
        self.conn = None

        self.frame = Frame(master)
        self.frame.pack(side = LEFT, anchor = N)
        self.startb = Button(self.frame, text = "Start", command = self.startc)
        self.startb.pack(side = LEFT, anchor = N)
        self.stopb = Button(self.frame, text = "Stop", command = self.stopc)
        self.stopb.pack(side = LEFT, anchor = N)
        self.connectionl = Label(self.frame, text = "not connected")
        self.connectionl.pack(side = LEFT, anchor = SW)

    def socket_thread(self):
        print("thread started..")
        self.ls = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        port = 9999
        self.ls.bind(('', port))
        print("Server listening on port %s" %port)
        self.ls.listen(1)
        self.ls.settimeout(5)
        self.conn=None
        while self.running != 0:
            if self.conn is None:
                try:
                    (self.conn, self.addr) = self.ls.accept()
                    print("client is at", self.addr[0], "on port", self.addr[1])
                    self.connectionl.configure(text="CONNECTED!")

                except socket.timeout,e:
                    print ("Waiting for Connection...")

                except Exception,e:
                    print("Connect exception: "+str(e) )

            if self.conn != None:
                print ("connected to "+str(self.conn)+","+str(self.addr))
                self.conn.settimeout(5)
                self.rc = ""
                connect_start = time() # actually, I use this for a timeout timer
                while self.rc != "done":
                    self.rc=''
                    try:
                        self.rc = self.conn.recv(1000).decode('utf-8')

                    except Exception,e:
                        # we can wait on the line if desired
                        print ("socket error: "+repr(e))

                    if len(self.rc):
                        print("got data", self.rc)
                        self.conn.send("got data.\n")
                        connect_start=time()  # reset timeout time
                    elif (self.running==0) or (time()-connect_start > 30):
                        print ("Tired of waiting on connection!")
                        self.rc = "done"

                print ("closing connection")
                self.connectionl.configure(text="not connected.")
                self.conn.close()
                self.conn=None
                print ("connection closed.")

        print ("closing listener...")
        # self running became 0
        self.ls.close()

    def startc(self):
        if self.running == 0:
            print ("Starting thread")
            self.running = 1
            self.thread=Thread(target=self.socket_thread)
            self.thread.start()
        else:
            print ("thread already started.")

    def stopc(self):
        if self.running:
            print ("stopping thread...")
            self.running = 0
            self.thread.join()
        else:
            print ("thread not running")   

root = Tk()
gui = Gui(root)
root.mainloop()
commented: Nice concerto for thread, sockets and gui! +14

I tried to make all the print statements python2/python3 compatible

Do you know you can use

 from __future__ import print_function

to get immediate compatibility ?

Thank you , Gribouillis!
I just discovered that today when I was working with some other python3 code where print statements were the only difference. I think

from __future__ import print_function 

will be at the start of all my programs from now on!

In python 2, I usually start with

from __future__ import (absolute_import, division,
                        print_function, unicode_literals)

but I write less and less python 2 code.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.