python socket服务器异步接收消息

时间:2018-03-13 09:48:58

标签: python sockets

我想在python中构建一个客户端/服务器应用程序,其中:

  • 客户端不断向服务器发送数据
  • 服务器异步接收此数据,即每当运行某个命令时它接收数据,否则忽略它

我试图制作一个示例代码来模拟这种行为,但问题是,当服务器尝试接收包时,它会收到自上次调用“recv”以来发送的所有数据。

问题是:有没有办法只接收最后一个包,即忽略之前发送的内容?

这是我使用流套接字的示例代码(我也尝试过UDP,相同的行为)

服务器端:

import socket
import multiprocessing
import testClient
import time

address = ('localhost', 50000)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(address)

#Start the client
client = multiprocessing.Process(target=testClient.testClient)
client.start()

s.listen(1)
conn, addr = s.accept()
print 'Received connection {}, {}'.format(conn, addr)
print 'Server> receiving data'
data = conn.recv(15)
print 'Server> received data',repr(data)
time.sleep(10)
print 'Server> receiving data'
data = conn.recv(15)
print 'Server> received data',repr(data)

客户方:

import socket
import time
import numpy

serverAddress = ('localhost', 50000)

def testClient():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('localhost', 50000))
    count = 0
    while True:  
        data = 'Test string %d'%count
        print '>client: sending data',data
        s.sendall(data)
        time.sleep(1)
        count +=1
    s.close()

示例输出:

>client: sending data Test string 0
Server> receiving data
Server> received data 'Test string 0'
>client: sending data Test string 1
>client: sending data Test string 2
>client: sending data Test string 3
>client: sending data Test string 4
>client: sending data Test string 5
>client: sending data Test string 6
>client: sending data Test string 7
>client: sending data Test string 8
>client: sending data Test string 9
Server> receiving data
Server> received data 'Test string 1Te'
...

我想第二次收到的是“测试字符串9”。有办法做到这一点还是完全不现实?

修改

根据迈克的回答,我意识到当我需要阅读更多数据时,我可能需要关闭连接并打开一个新连接。该解决方案可以使用数据报套接字来实现。这是我的工作示例:

服务器端

import socket
import multiprocessing
import testClientUDP
import time


sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

server_address = ('localhost', 10000)
print 'Server> starting up on %s port %s' % server_address
sock.bind(server_address)

#Start client process
client = multiprocessing.Process(target = testClientUDP.testClient)
client.start()

data, address = sock.recvfrom(4096)
print 'Server> received data: ',data

#Close socket
sock.close()

time.sleep(5)
#Open a new socket 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(server_address)

data, address = sock.recvfrom(4096)
print 'Server> received data: ',data
sock.close()

time.sleep(5)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(server_address)

data, address = sock.recvfrom(4096)
print 'Server> received data: ',data

sock.close()

客户端

import socket
import time

def testClient():
    # Create a UDP socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

    server_address = ('localhost', 10000)

    try:
        count = 0        
        while True:
            # Send data
            data = 'Test message %d'%count
            print 'Client> sending "%s"' %data
            sent = sock.sendto(data, server_address)
            time.sleep(1)
            count += 1

    finally:
        print 'Client> closing socket'
        sock.close()

输出

Server> starting up on localhost port 10000
Client> sending "Test message 0"
Server> received data: Test message 0
Client> sending "Test message 1"
Client> sending "Test message 2"
Client> sending "Test message 3"
Client> sending "Test message 4"
Client> sending "Test message 5"
Server> received data: Test message 5
Client> sending "Test message 6"
Client> sending "Test message 7"
Client> sending "Test message 8"
Client> sending "Test message 9"
Client> sending "Test message 10"
Server> received data: Test message 10 
Client> sending "Test message 11"
Client> sending "Test message 12"
...

1 个答案:

答案 0 :(得分:0)

睡觉,等待“所需”的消息将无法正常工作,因为它仍然是相同的连接,并且流上有数据堆积起来。

选项1:

一种方法是在while循环中调用conn.recv(1024)(您可以使用任何其他值,1024适用于大多数情况),直到流为“空”并丢弃您所在的8个消息块不感兴趣(使用计数器变量)。

选项2:

如果您确切地知道堆积了多少比特,您也可以使用conn.recv(13)接收您的第一条消息,然后休眠,然后拨打conn.recv(13*8)(读取您的13位消息的8倍 - 这是数据1-9,你不想要的),下次你从流中读取它时,它将包含你的第9条消息。

然而,这在很大程度上依赖于知道客户端将发送多少位,因此第一个选项会更好。