Python 3.3.3聊天程序

时间:2014-01-03 19:39:31

标签: python sockets

我一直在处理的代码似乎不允许连接,或返回错误,或做任何事情。我无法弄清楚什么是错的,因为没有错误被抛出。任何人都可以帮我调试。客户端应该在按钮单击时发送文本,服务器只接收并打印消息。正如我所说,该程序运行,但没有打印任何东西,并没有做任何事情后显示错误或问题所以我无法确定如何解决它。任何帮助将不胜感激。

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()

1 个答案:

答案 0 :(得分:3)

这里有三个主要问题,还有一些较小的问题。

首先,正如丹尼尔罗斯曼所说,只是调用方法New_Thread并不会神奇地使它成为线程。

但这很容易解决。您可以这样做,而不是调用SRV.New_Thread()

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

如果您解决了这个问题,服务器现在将开始在后台收听。但是你会发现,即使在服务器启动之前,客户端甚至可以在点击任何内容之前立即打印出“连接被拒绝”。然后,单击该按钮不会再次尝试。

问题在于:

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

在初始化期间,您调用 self.buttonClick(),然后将该方法调用的返回值指定为按钮的command。你想要做的是使方法本身成为按钮的命令。像这样:

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

接下来,当您单击该按钮时,仍然会“拒绝连接”。为什么服务器拒绝您的连接?

不是。这是你自己的错误处理误导你。无论如何,您都会为任何例外打印该消息。如果你改变它来做到这一点:

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

您会看到实际问题是:

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

如果您在代码中看得更远,如果self.p == '',则永远不会设置port;相反,您设置了self.p


如果你修复了所有这些,当你点击按钮时,它就会连接。


还有一些其他问题。仅举一个例子:您的服务器代码只接受一个连接,从中读取一次,然后退出。因此,如果您单击按钮两次,客户端将尝试第二次连接,并等待永远,因为没有人接受连接。 (如果你真的关闭了套接字,你至少会得到一个错误,而不是永远阻塞。)如果你想让按钮多次工作,你需要在{{1}周围放置一个while True:循环代码,所以它会在每个完成后等待新的连接。