为什么我的管道坏了(python套接字)

时间:2015-04-27 05:45:41

标签: python sockets network-programming

#!/usr/bin/python

from tkinter import *
from tkinter.ttk import *
from socket import *
import select

class window(Frame):

    def __init__(self, parent, name, networker):
        self.networker = networker
        self.name=name
        self.count=0
        self.scrollx=900
        self.scrolly=0

        self.messageStr=""
        Frame.__init__(self, parent)
        self.parent = parent

        self.parent.title("Chat")
        self.style = Style()
        self.style.theme_use("default")

        self.pack(fill=BOTH, expand="yes")

        self.lfone = Frame(self)

        self.messageCanvas = Canvas(self.lfone, relief=RAISED, height=0, width=0, scrollregion=(0,0,self.scrollx,self.scrolly))


        self.myentry = Entry(self)
        self.sendbutton = Button(self, text="Send", command=self.sendbuttoncommand)
        self.scrollbar = Scrollbar(self.lfone)


        self.lfone.pack(fill=BOTH, expand="yes")
        self.myentry.pack(side=LEFT, fill=BOTH, expand="yes", padx=5)

        self.messageCanvas.pack(side=LEFT, fill=BOTH, expand="yes", padx=5, pady=5)
        self.sendbutton.pack(side=RIGHT, padx=5)
        self.scrollbar.pack(side=RIGHT, fill=Y, pady=5)


        self.messageCanvas.configure(yscrollcommand=self.scrollbar.set)
        self.scrollbar.config(command=self.messageCanvas.yview)

        self.doListen()

    def sendbuttoncommand(self):
        self.count=self.count+20
        self.scrolly=self.scrolly+20
        str = (self.name + ": " + self.myentry.get())
        b = bytearray(str, "utf-8")
        self.messageCanvas.create_text(5, self.count, anchor=SW, text=(self.name + ": " + self.myentry.get()))
        self.messageCanvas.config(scrollregion=(0,0,self.scrollx, self.scrolly))
        self.networker.myhost.send(b)

    def post(self, str):
        self.count=self.count + 20
        self.scrolly=self.scrolly+20
        self.messageCanvas.create_text(5, self.count, anchor=SW, text=str)
        self.messageCanvas.config(scrollregion=(0,0,self.scrollx, self.scrolly))

    def doListen(self):
        str = self.networker.listen()
        if str != "":
            self.post(str)
        self.after(128, self.doListen)

class splash(Frame):

    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent=parent
        parent.title("INIT")
        self.splashed=False
        self.initgui()

    def initgui(self):
        self.style = Style()
        self.style.theme_use("default")
        self.pack(fill=BOTH, expand=YES)

        self.label = Label(self, text="Choose a name")
        self.entry = Entry(self)
        self.button = Button(self, text="Submit", command=lambda: self.doSplash())
        self.ipentry = Entry(self)
        self.iplabel = Label(self, text="IP addr to connect to:")

        self.label.pack(side=TOP, pady=5)
        self.entry.pack(fill=X, expand=YES, padx=5)
        self.iplabel.pack()
        self.ipentry.pack(fill=X, padx=5)
        self.button.pack(side=BOTTOM, pady=5)

    def doSplash(self):
        self.name=self.entry.get()
        #TODO: exception handling for ip addr
        self.addr=self.ipentry.get()
        self.splashed=True
        self.parent.destroy()

class networker():

    def __init__(self):
        self.myhost = socket(AF_INET, SOCK_STREAM)
        self.myclient = socket(AF_INET, SOCK_STREAM)
        self.host=gethostname()
        self.port=2007
        self.myhost.bind((self.host,self.port))
        self.myhost.listen(5)
        self.clientConnected=False
        self.myhost.setblocking(0)

    def connectToHost(self, hostname):
        self.myclient.connect((hostname,self.port))

    def getClient(self):
        self.client, self.addr = self.myhost.accept()
        print("Got a connection from %s" % str(self.addr))
        self.clientConnected=True

    def listen(self):
        ready = select.select([self.myclient], [], [], 1)
        if ready == 0:
            str = self.myclient.recv(1024)
            return str
        return ""



def main():

    myN = networker()

    splashRoot = Tk()
    splashApp=splash(splashRoot)
    splashRoot.mainloop()

    myN.connectToHost(splashApp.addr)
    myN.getClient()

    if splashApp.splashed:
        root = Tk()
        root.geometry("900x600+300+300")
        app=window(root, splashApp.name, myN)
        root.mainloop()

if __name__ == '__main__':
    main()

所以这应该是一个简单的聊天程序。对不起所有的代码,但我担心如果我把它切掉它是没有意义的。

这个想法: networker对象连接到输入的IP地址(在我的测试用例中,我自己的addr)并报告其成功。 window接受一个networker对象并在doListen()中调用它的listen()方法。 doListen()使用after来执行多任务侦听和维护gui。 sendbuttoncommand()应该在条目中将消息发布到客户端和发送者的屏幕,但是是错误的来源。

大部分都有效,并声称连接成功。但是,当我尝试使用window.sendbuttoncommand()时,我收到一个损坏的管道错误。我对python和网络编程都很陌生,并且不知道十亿内容中的哪一个导致了这一点。我的一些想法:

  1. 将网络对象传递给窗口对象可能会破坏连接,因为它不是像我假设的那样简单地传递引用。

  2. 在window.dolisten()中使用after可能导致服务器只监听短暂的时间段,并且在该时间段内没有捕获数据。

  3. 连接到我自己的设备可能会搞砸了。

  4. 非常感谢任何建议/帮助/见解。

1 个答案:

答案 0 :(得分:0)

这个问题的答案不是做我想做的事情而是使用像扭曲的东西。无需重新发明轮子