user3158371
user3158371

Reputation:

Python 3.3.3 Chat Program

The code I've been working on doesn't seem to permit a connection, or return errors, or do anything. I can't figure out what's wrong since no errors are thrown. Can anyone help me debug. The client is supposed to send text on button click and the server just receives and prints messages. As I said, the program runs, but doesn't print anything and doesn't do anything after to show errors or issues so I can't identify how to fix it. Any assistance would be appreciated.

import sys, os, time, socket, tkinter
from tkinter import *

HOST = ''
PORT = 31337
BUFF = 4096
DATA = [8000]
CNCT = 5
NAME = ''
ADDRESS_LIST = []

try:
    SOCK = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
    print('Failed to create socket')
    sys.exit()

class CLIENT():
    def __init__(self):
        self.h = 'localhost'
        self.p = 31337
        self.t = 'HELLO!'
        top = tkinter.Tk()
        top.geometry('400x200')
        top.title('CHAT WITH ME!')
        self.host = tkinter.Entry(top)
        self.host.place(x=37,y=25)
        self.host.bind('<Key-Return>',self.ret_host())
        self.port = tkinter.Entry(top)
        self.port.place(x=200,y=25)
        self.port.bind('<Key-Return>',self.ret_port())
        self.text = tkinter.Entry(top)
        self.text.place(x=110,y=50)
        self.text.bind('<Key-Return>',self.ret_text())
        but1 = tkinter.Button(top, text ="send", command = self.buttonClick())
        but1.place(x=0,y=20)
        mb = Menu(tkinter.Menu(), tearoff=0)
        lt = len(ADDRESS_LIST)
        #mb.add_checkbutton(label="FRIEND" + str(lt), variable = ADDRESS_LIST[lt-1])
        top.mainloop()

    def ret_host(self):
        self.h = self.host.get()

    def ret_port(self):
        self.p = self.port.get()

    def ret_text(self):
        self.t = self.text.get()

    def buttonClick(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if self.p == '':
            self.p = 31337
        else:
            port = int(self.p)
        if self.h == '':
            self.h = 'localhost'
        ADDRESS_LIST.append(self.h)
        try:
            sock.connect((self.h, port))
            sock.sendall(bytes(self.t,'ascii'))
        except:
            print('connection refused')
        finally:
            sock.close()

class SERVER():
    conn = ''
    addr = 'localhost'
    data = ''
    trth = False
    host = ''
    port = ''

    def __init__(self):
        SOCK.bind((HOST, PORT))
        SOCK.listen(CNCT)

    def New_Thread(self):
        sock = SOCK
        self.conn, self.addr = sock.accept()
        if self.addr == '':
            trth = False
            print(self.addr)
        else:
             print('Got connection from ', self.addr)
             self.rcvr()
             trth = True

    def rcvr(self):
        data = self.conn.recv(BUFF)
        if not data:
            print('no data')
        else:
            #ADDRESS_LIST.append(self.addr)
            #print(len(ADDRESS_LIST))
            print(str(self.addr) + '> ', data)

SRV = SERVER()
SRV.New_Thread()
CLIENT()

Upvotes: 0

Views: 1467

Answers (1)

abarnert
abarnert

Reputation: 365597

You have three major problems here, as well as a slew of smaller ones.

First, as Daniel Roseman says, just calling a method New_Thread doesn't magically make it threaded.

But that's easy to fix. Instead of calling SRV.New_Thread(), you can just do this:

threading.Thread(target=SRV.New_Thread).start()

If you fix that, the server will now start listening in the background. But you'll see that the client prints out "connection refused" immediately, before you can even click anything, even before the server gets started. And then, clicking the button doesn't make it try again.

The problem is here:

but1 = tkinter.Button(top, text ="send", command = self.buttonClick())

During initialization, you're calling self.buttonClick(), and then assigning the return value from that method call as the button's command. What you want to do is make the method itself be the button's command. Like this:

but1 = tkinter.Button(top, text ="send", command = self.buttonClick)

Next, when you click the button, you still get "connection refused". Why is the server refusing your connection?

It's not. That's your own error handling misleading you. You print out that message for any exception, no matter what. If you change it to do this:

except Exception as e:
    print('failed to connect:', e)

You'll see that the actual problem is:

failed to connect: local variable 'port' referenced before assignment

And if you look farther up in your code, if self.p == '', you never set port; instead, you set self.p.


And if you fix all of those, when you click the button, it will connect.


There are still some other problems. Picking just one example: your server code just accepts one connection, reads from it once, then exits. So, if you click the button twice, the client tries to connect a second time, and waits forever because nobody's accepting the connection. (If you'd actually closed the socket, you'd at least get an error instead of blocking forever.) If you want the button to work multiple times, you need to put a while True: loop around the New_Thread code, so it will wait for a new connection after each one finishes.

Upvotes: 3

Related Questions