Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中从外部套接字对象发送数据_Python_Sockets_Asynchronous_Stack - Fatal编程技术网

在python中从外部套接字对象发送数据

在python中从外部套接字对象发送数据,python,sockets,asynchronous,stack,Python,Sockets,Asynchronous,Stack,我创建了一个Clientsocket对象,我实例化了它,它保持了与服务器的连接,工作正常,但我想知道是否有方法从实例外部调用socket.send事件。我准备为消息创建一个堆栈,并检查while循环中的堆栈,如果它不是空的,则将最旧的数据发送到服务器,这对我来说很好,但我的问题是堆栈仅在while循环之后更新(我尝试中断,然后更新)。 所以我的问题是,有没有一种方法可以在运行while循环的同时更新全局堆栈?或者是否有其他方法调用套接字。在对象外部发送事件 import socket impor

我创建了一个
Client
socket对象,我实例化了它,它保持了与服务器的连接,工作正常,但我想知道是否有方法从实例外部调用
socket.send
事件。我准备为消息创建一个堆栈,并检查while循环中的堆栈,如果它不是空的,则将最旧的数据发送到服务器,这对我来说很好,但我的问题是堆栈仅在while循环之后更新(我尝试中断,然后更新)。 所以我的问题是,有没有一种方法可以在运行while循环的同时更新全局堆栈?或者是否有其他方法调用
套接字。在对象外部发送
事件

import socket
import sys
import select
import threading

SERVER_IP = '192.168.1.4'
PORT = 8686
TIMEOUT = 5
BUF_SIZE = 1024
MESSAGES = ['testdata1', 'testdata2']

class Client(threading.Thread):

    def __init__(self, host=SERVER_IP, port=PORT):
        threading.Thread.__init__(self)
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock = socket.create_connection((host, port), 1)
        self.sock.setblocking(0)
        while 1:
            try:
                global MESSAGES
                ready = select.select([self.sock], [], [], TIMEOUT*1000)
                if ready[0]:
                    buf = self.sock.recv(BUF_SIZE)
                    print buf
                    #TODO:do stuff with buf

                    print 'messages left:'+str(len(MESSAGES))
                    if len(MESSAGES)>0:
                        self.sock.send(MESSAGES.pop())
            except KeyboardInterrupt:
                self.sock.close()
                sys.exit(1)
            except Exception, e:
                print '\n[ERR] %s' % e
                self.sock.close()
                sys.exit(1)

    def run(self):
        pass

    def sendData(self, data):
        global MESSAGES
        print 'appending data:%s' % data
        MESSAGES.append(data)

def main():
    client = Client()
    client.start()
    client.sendData("test1")
    client.sendData("test2")
    client.sendData("test3")

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        sys.exit(1)

如果将循环从

__init__() into run()
方法

您的线程不是这样的线程,进程块位于client=client(…)

为什么要混合选择和线程?这真的有必要吗?如果您想要无线程的异步发送和接收,请使用asyncore模块。 或者从代码中删除select。socket.recv()将一直阻塞,直到它以阻塞模式接收数据为止,但由于这是一个线程,我看不出有任何错误。如果在非阻塞模式下,如果没有要接收的数据(如果我记得正确),recv()将只返回None。所以你真的不需要选择。只需检查recv()是否返回None。如果是的话,在再试之前先睡一会儿


您这样做的方式两次困扰您的操作系统。一次用于读取套接字,第二次用于获取套接字的状态,其中timeout用于模拟sleep()而不是其他任何东西。然后循环再次检查,在超时后立即进行select()系统调用,确认该套接字无需执行任何操作。

如果将循环从

__init__() into run()
方法

您的线程不是这样的线程,进程块位于client=client(…)

为什么要混合选择和线程?这真的有必要吗?如果您想要无线程的异步发送和接收,请使用asyncore模块。 或者从代码中删除select。socket.recv()将一直阻塞,直到它以阻塞模式接收数据为止,但由于这是一个线程,我看不出有任何错误。如果在非阻塞模式下,如果没有要接收的数据(如果我记得正确),recv()将只返回None。所以你真的不需要选择。只需检查recv()是否返回None。如果是的话,在再试之前先睡一会儿

您这样做的方式两次困扰您的操作系统。一次用于读取套接字,第二次用于获取套接字的状态,其中timeout用于模拟sleep()而不是其他任何东西。然后,循环再次检查,在超时后立即进行select()系统调用,确认该套接字无需执行任何操作。

客户端。

初始化()不会返回,因为它进入无限while循环。因此,控制永远不会返回到主线程,
客户机
线程实际上没有启动

相反,您应该将while循环移动到
run()
方法中。然后
\uuuu init\uuuu()
方法将控制权返回主线程,然后主线程可以启动线程,并请求客户端通过
sendData()
发送消息

您可能不应该使用全局
消息列表
来创建主线程和工作线程之间的通信,尤其是在多个工作线程正在运行的情况下。类似这样(未经测试!):

Client.\uuuu init\uuuuu()
不会返回,因为它进入无限while循环。因此,控制永远不会返回到主线程,
客户机
线程实际上没有启动

相反,您应该将while循环移动到
run()
方法中。然后
\uuuu init\uuuu()
方法将控制权返回主线程,然后主线程可以启动线程,并请求客户端通过
sendData()
发送消息

您可能不应该使用全局
消息列表
来创建主线程和工作线程之间的通信,尤其是在多个工作线程正在运行的情况下。类似这样(未经测试!):


由于您的答案包含了与我相同的信息,但您添加了一些代码,请考虑在没有选择的情况下添加代码,正如我所建议的。否则我会把它加到我的答案里。或者,使用Queue()表示速度对于加快速度没有太大意义。我认为这是一个小型客户端应用程序,所以这些数据类型之间的差异不会有多大影响。但是用不必要的系统调用来干扰操作系统会增加CPU的使用。@Dalen:我的回答中包含了一些与你的相同的信息,但我的回答进一步提出了在主线程和(可能)多个工作线程之间进行通信的线程安全方式。这是一个更好的体系结构,当然比使用全局变量要好。关于速度,问题是什么?OP没有提到一个,而且
Queue
并不慢。@Dalen:关于线程中
select()
的使用,正如你所说的,并不理想。在本例中,最好只执行阻塞
recv()
,尽管不难想象主线程可能希望向工作线程发送消息以控制它,例如quit命令。在这种情况下,使用
select()
并不是不合理的,因此我将保留我的答案。我同意,但正如我所解释的,这不是客户机速度的问题。它只会使一个系统调用超出需要。select()很快,是的,但是为什么要先用syscall来打扰操作系统,然后select()自己反复检查套接字5秒钟呢。如果超时时间更小,select()对套接字的影响更小,但对操作系统的影响更大。至于线程安全,首先,我建议OP尽可能不要将消息存储在全局变量中
import Queue

class Client(threading.Thread):

    def __init__(self, msg_queue, host=SERVER_IP, port=PORT):
        threading.Thread.__init__(self)
        self.msg_queue = msg_queue
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock = socket.create_connection((host, port), 1)
        self.sock.setblocking(0)

    def run(self):
        while 1:
            try:
                ready = select.select([self.sock], [], [], TIMEOUT*1000)
                if ready[0]:
                    buf = self.sock.recv(BUF_SIZE)
                    print buf
                    #TODO:do stuff with buf

                    print 'messages left:'+ str(self.msg_queue.qsize())
                    try:
                        msg = self.msg_queue.get_nowait()
                        self.sock.send(msg)
                    except Queue.Empty:
                        pass
            except KeyboardInterrupt:
                self.sock.close()
                sys.exit(1)
            except Exception, e:
                print '\n[ERR] %s' % e
                self.sock.close()
                sys.exit(1)

def main():
    # create a queue and pass it to the client
    msg_queue = Queue.Queue()
    client = Client(msg_queue)
    client.start()
    msg_queue.put("test1")
    msg_queue.put("test2")
    msg_queue.put("test3")