Python套接字客户端/服务器选择问题

时间:2016-01-19 18:23:01

标签: python sockets

我们正试图让我们的python信使系统更有效率。目前,客户端和服务器在运行和通信时都使用了大量的CPU。我们怀疑这是由于接收/连接循环不断尝试接收消息或用户/密码。 消息接收循环如下:

def recvmsg():
    global decrypted_text
    while not shutdown:
            response = s.recv(4096).decode('utf-8')
            response = decrypt(response)

            if response.startswith("dict_keys(['"):
                    formatted = response.replace("dict_keys(['", "")
                    formatted = formatted.replace("'])", "")
                    formatted = formatted.replace("'", "")

                    output_field.configure(state = "normal")
                    output_field.insert(END, "Connected users: " + formatted + "\n")
                    output_field.see(END)
                    output_field.configure(state = "disabled")                         
            else:
                    output_field.configure(state = "normal")
                    output_field.insert(END, response + "\n")
                    output_field.see(END)
                    output_field.configure(state = "disabled")

我们正在尝试利用select模块让循环等待传入流量而不是循环并且无法进入无穷大。 我们在这里看了一下:http://ilab.cs.byu.edu/python/select/echoserver.html但是我们没有达到很远,因为我们收到了这个错误: [WinError 10022]提供了无效的参数。我们还在这里查看了python文档:https://docs.python.org/3/library/select.html?highlight=select#module-select

1 个答案:

答案 0 :(得分:0)

您可能会发现this answer有助于实施您的服务器。如果您希望更完整的服务器实现,也可以提供。在开发复杂版本的服务器时,开发了各种功能,包括朋友列表,私人消息和个人通信渠道。

<强> Simple_Server.py

#! /usr/bin/env python3
import socket, select

def main():
    a = [socket.socket(socket.AF_INET, socket.SOCK_STREAM)]     # socket array
    a[0].bind(('', 8989))
    a[0].listen(5)
    while True:
        for b in select.select(a, [], [])[0]:                   # ready socket
            if b is a[0]:
                a.append(b.accept()[0])
            else:
                try:
                    c = b.recv(1 << 12)                         # sent message
                except socket.error:
                    b.shutdown(socket.SHUT_RDWR)
                    b.close()
                    a.remove(b)
                else:
                    for d in (d for d in a[1:] if d is not b):  # message sink
                        d.sendall(c)

if __name__ == '__main__':
    main()

<强> MultichatClient.py

#! /usr/bin/env python3
from safetkinter import *
from tkinter.constants import *
import socket
import sys

class MultichatClient(Frame):

    after_handle = None

    def __init__(self, master, remote_host):
        super().__init__(master)
        self.message_area = ScrolledText(self, width=81, height=21,
                                         wrap=WORD, state=DISABLED)
        self.message_area.grid(sticky=NSEW, columnspan=2)
        self.send_area = Entry(self)
        self.send_area.bind('<Return>', self.keyPressed)
        self.send_area.grid(sticky=EW)
        b = Button(self, text='Send', command=self.mouseClicked)
        b.grid(row=1, column=1)
        self.send_area.focus_set()
        try:
            self.remote = socket.create_connection((remote_host, 8989))
        except socket.gaierror:
            print('Could not find host {}.'.format(remote_host))
        except socket.error:
            print('Could not connect to host {}.'.format(remote_host))
        else:
            self.remote.setblocking(False)
            self.after_handle = self.after_idle(self.dataready)
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)

    @classmethod
    def main(cls, args):
        root = Tk()
        root.title('MultichatClient version 1.0')
        m = cls(root, args[0])
        m.grid(sticky=NSEW)
        root.grid_rowconfigure(0, weight=1)
        root.grid_columnconfigure(0, weight=1)
        root.mainloop()
        return 1

    def dataready(self):
        try:
            s = self.remote.recv(1 << 12).decode()
        except socket.error:
            pass
        else:
            self.message_area['state'] = NORMAL
            self.message_area.insert(END, s)
            self.message_area['state'] = DISABLED
            self.message_area.see(END)
        self.after_handle = self.after(100, self.dataready)

    def destroy(self):
        if self.after_handle:
            self.after_cancel(self.after_handle)
        super().destroy()

    def mouseClicked(self, e=None):
        self.remote.sendall(self.send_area.get().encode() + b'\r\n')
        self.send_area.delete(0, END)

    keyPressed = mouseClicked

if __name__ == '__main__':
    sys.exit(MultichatClient.main(sys.argv[1:]))