Python 套接字监听

标签 python sockets python-2.7

下面提到的所有内容都是在使用 python 2.7 的 Windows 机器上

你好,

我目前正在尝试在套接字上监听远程程序发送的数据。然后将此数据打印到屏幕并请求用户输入,然后将其返回到远程程序。在测试中,我已经能够让远程程序向我发送命令行程序(cmd、ipconfig、whoami、ftp)的菜单,然后我的程序返回一个数字作为菜单选项的选择。

远程程序收到我的响应并发送所选命令的输出。 ipconfig 和 whoami 工作完美,但 cmd 和 ftp 只返回一次终端输出。 (即,我可以在 FTP 程序中输入一个命令,然后再将它发送到远程程序,然后我再也听不到回复了)

我的代码失败的部分是 if ready[0]: 永远不会在第一次对话后再次准备就绪。

我知道远程程序运行正常,因为我可以使用 netcat 代替我的代码并无限期地操作 cmd 终端。

我如何着手正确实现可以处理此类连接的 python 套接字监听器?

我的“程序”的全部内容:

import socket, sys, struct, time, select

host = ''
port = 50000
connectionSevered=0

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
    print 'Failed to create socket'
    sys.exit()
print '[+] Listening for connections on port '+str(port)+'.'

s.bind((host,port))
s.listen(5)         

def recvall(the_socket,timeout=2):
    global connectionSevered
    data='';          # Data found by recv
    total_data=[];    # Finally list of everything

    s.setblocking(0)  #make socket non blocking
    begin=time.time() #beginning time

    while 1:
        ready = select.select([client], [], [], .2)
        if time.time()-begin > timeout:
            print 'Timeout reached'
            #Leave loop, timer has reached its threshold
            break
        if ready[0]:
            print 'In ready loop!'
            try:
                data = client.recv(4096)    #attempt to fetch data
                if data:
                    begin=time.time()       #reset timeout timer
                    total_data.append(data) 
                    data='';
            except socket.error:
                print '[+] Lost connection to client. Printing buffer...'
                connectionSevered=1   # Let main loop know connection has errored
                pass
        time.sleep(1)
    #join all parts to make final string
    return ''.join(total_data)

client, address = s.accept()
print '[+] Client connected!'

while (connectionSevered==0): # While connection hasn't errored
    print "connectionSevered="+str(connectionSevered) # DEBUG
    recvall(s)
    response = raw_input()                  #take user input
    client.sendto(response)                   #send input
client.close(0)

如果您需要更多信息,请告诉我,我们将不胜感激,我对此很陌生,渴望学习。

最佳答案

玩了一会儿终于让它在本地使用 python 2.7 的 telnet session 中工作得很好。

它所做的是设置一个线程,该线程在客户端连接监听客户端内容时运行。

当客户端发送返回(如果您与 Linux 系统交互,“\r\n”可能必须更改它?)时,消息会打印到服务器,而如果在服务器端这将被发送到客户端:

import socket
import threading
host = ''
port = 50000
connectionSevered=0

class client(threading.Thread):
    def __init__(self, conn):
        super(client, self).__init__()
        self.conn = conn
        self.data = ""
    def run(self):
        while True:
            self.data = self.data + self.conn.recv(1024)
            if self.data.endswith(u"\r\n"):
                print self.data
                self.data = ""

    def send_msg(self,msg):
        self.conn.send(msg)

    def close(self):
        self.conn.close()

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((host,port))
    s.listen(5)
except socket.error:
    print 'Failed to create socket'
    sys.exit()

print '[+] Listening for connections on port: {0}'.format(port)


conn, address = s.accept()
c = client(conn)
c.start()
print '[+] Client connected: {0}'.format(address[0])
c.send_msg(u"\r\n")
print "connectionSevered:{0}".format(connectionSevered) 
while (connectionSevered==0):
    try:
        response = raw_input()  
        c.send_msg(response + u"\r\n")
    except:
        c.close()

以上答案不适用于多个连接。我已经通过添加另一个线程来更新它来获取连接。现在可以连接多个用户。

import socket
import threading
import sys
host = ''
port = 50000

class client(threading.Thread):
    def __init__(self, conn):
        super(client, self).__init__()
        self.conn = conn
        self.data = ""

    def run(self):
        while True:
            self.data = self.data + self.conn.recv(1024)
            if self.data.endswith(u"\r\n"):
                print self.data
                self.data = ""

    def send_msg(self,msg):
        self.conn.send(msg)

    def close(self):
        self.conn.close()

class connectionThread(threading.Thread):
    def __init__(self, host, port):
        super(connectionThread, self).__init__()
        try:
            self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.s.bind((host,port))
            self.s.listen(5)
        except socket.error:
            print 'Failed to create socket'
            sys.exit()
        self.clients = []

    def run(self):
        while True:
            conn, address = self.s.accept()
            c = client(conn)
            c.start()
            c.send_msg(u"\r\n")
            self.clients.append(c)
            print '[+] Client connected: {0}'.format(address[0])



def main():
    get_conns = connectionThread(host, port)
    get_conns.start()
    while True:
        try:
            response = raw_input() 
            for c in get_conns.clients:
                c.send_msg(response + u"\r\n")
        except KeyboardInterrupt:
            sys.exit()

if __name__ == '__main__':
    main()

客户端无法看到其他客户端所说的内容,来自服务器的消息将发送给所有客户端。我将把它作为练习留给读者。

关于Python 套接字监听,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15869158/

相关文章:

macos - python : Check if a directory is an alias

python - Pycharm环境不同于命令行

python - 在 MultiIndex 中为缺失日期插入 0 值

java - 是否可以在单个端口上运行两个 NIO 服务器套接字?

python - 每次当我想使用多个 python 版本中的 python3 时,都需要取消设置 PYTHONPATH

c - 如果我使用 select() 服务器编写一个对等 2 个对等应用程序而不使用 fork()、线程、共享内存、信号量,这样可以吗?

python - 套接字程序崩溃后无法绑定(bind)到地址

python - PyGame 获取 Sprite 组

python - 如何使用 tkinter GUI python 创建 9*9 数独生成器?

python - 使用 python 读取 .txt 数据