如何通过“选择”继续监听连接的TCP套接字

时间:2015-11-09 01:21:40

标签: python sockets select tcp

我所有的客户端套接字都做同样的事情:每秒发送一个包(22个字节)

服务器代码如下:

import select
import socket
import datetime
SList = []


class Tserver:

    def __init__(self, portNum):
        host = '127.0.0.1'
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server.bind((host, portNum))
        self.server.listen(1)


def GETPACK():
    # function for CRC check
    def CRC(DATA_STR):
        return 1

    # generate 100 sockets to listen
    for x in range(100):
        SList.append(Tserver(x+10000))

    inputs = []
    # put in inputs
    for x in range(100):
        inputs.append(SList[x].server)

    while(True):
        ready_socks, _, _ = select.select(inputs, [], [])
        for sock in ready_socks:
            c, addr = sock.accept()
            while(True):
                data = c.recv(22)
                if len(data) == 22:  # To make sure the data-length is 22
                    # Turn the pack string into bytearray
                    data_bytes = bytearray()
                    data_bytes.extend(data)
                    if CRC(data_bytes) == 1:
                        print "Connected from client IP Address:" + str(addr)
                        # ID
                        ID = 256*data_bytes[1] + data_bytes[2]
                        print "ID: ", ID
                        now = datetime.datetime.now()
                        print "now: ", str(now)

if __name__ == "__main__":
    GETPACK()

我的服务器只能打印第一个连接套接字发送的包。 我的问题是如何在将包发送到服务器时从每个端口打印出所有消息。

2 个答案:

答案 0 :(得分:1)

有关如何使用select模块编写基于选择的服务器的详细说明,请参阅this PyMOTW entry

该示例与您的代码之间的主要区别是:

您只需创建一个侦听套接字 - server。无需监听多个端口。

变量inputs将是一个由server组成的列表以及与客户端的任何其他打开套接字连接。

您的服务循环将如下所示:

while true:
  readable, _, _ = select.select(inputs, [], [])
  for r in readable:
    if r is server:
      # handle a new incoming connection
      # this will add an entry to the variable inputs
    else:
      # read some data from socket r and process it

当您尝试从客户端套接字读取并获得EOF条件时,您可以关闭该套接字并将其从inputs变量中删除。

答案 1 :(得分:0)

@ErikR感谢您的帮助,我更改了我的代码,并且工作正常。

我的代码不起作用的原因是由于两件事:

1.我只创建一个连接来从我的客户端收集数据。

2.如果客户端没有重新连接,则recv不能再次接受相同的连接。(我的代码在客户端关闭时不检查异常)

代码如下:

import select, socket, datetime
SList = []
SconnList = []

class Tserver:
    def __init__(self, portNum):
        host = '127.0.0.1'
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
        self.server.bind((host,portNum))
        self.server.listen(1)
        print "Server ports: "+str(portNum)

class Sconn:
    def __init__(self, sock):
        self.conn, self.addr = sock.accept()        

def GETPACK():
    # function for CRC check
    def CRC(DATA_STR):
        return 1

    # generate 100 sockets to listen        
    for x in range(100):
        SList.append(Tserver(x+10000))

    inputs = []
    # put in inputs
    for x in range(100):
        inputs.append(SList[x].server)

    while(True):
        ready_socks,_,_ = select.select(inputs, [], [])
        for sock in ready_socks:
            try:
                SconnList.append(Sconn(sock))
                SconnList.reverse()
                inputs.append(SconnList[0].conn)
            except:     
                data = sock.recv(22)
                if len(data) == 22: # To make sure the data-length is 22
                #Turn the pack string into bytearray
                    data_bytes = bytearray()
                    data_bytes.extend(data)
                    if CRC(data_bytes) == 1:
                        print "IP Address:" + str(sock.getsockname())
                        #ID
                        ID = 256*data_bytes[1] + data_bytes[2]
                        print "ID: ",ID
                        now =  datetime.datetime.now()
                        print "now: ",str(now)
                        print ""
                        print ""

if __name__ == "__main__":
    GETPACK()