2013-04-07 63 views
10

下面提到的全部是使用Python 2.7Python的插座听

你好,

我目前试图将套接字上侦听数据由远程程序发送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) 

请让我知道如果你需要更多的信息,任何帮助将不胜感激,我很新的这一点,好学。

+2

您是否尝试过使用“SocketServer”类?它有很好的文档记录,似乎比“套接字”更容易使用(也可以用于侦听):http://docs.python.org/2/library/socketserver.html – halflings 2013-04-08 00:04:01

+0

这太复杂了,什么你想达到什么目的? – tomasz 2013-04-11 20:54:22

回答

12

玩了这一段时间终于得到它在本地使用python 2.7 telnet会话很好。

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

当客户端发送一个返回(“\ r \ n”可能必须改变,如果您与Linux系统交互?)消息被打印到服务器,而这种情况发生时,如果有一个原始输入在服务器端将发送到客户端:

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() 

客户是不是能够看到其他客户说,来自服务器的消息将被发送到所有客户端。我将把它作为读者的练习。

+0

出于兴趣,当你在同一台PC上运行上面的python脚本时,当你打开一个CMD窗口并键入telnet localhost 50000时,如果你输入Hello,然后敲回车,什么都不会发生。你知道如何从Windows Telnet会话中推送终止字符串吗? – Bertie 2015-04-13 14:41:57

+0

我刚刚在Windows会话中运行脚本,当您在telnet屏幕中按Enter键时,您正在运行脚本的cmd中打印出hello。你期望发生什么? – Noelkd 2015-04-13 15:02:23

+0

当我使用Anaconda(和Spyder IDE)时,我正在通过IPython启动该程序。看起来,当我使用Python控制台启动程序时,它确实起作用,并且我看到远程登录显示在Python程序中,唯一的问题是如果我尝试从网络上的另一台计算机进行第二次连接,同时,它不连接?你知道为什么吗? – Bertie 2015-04-13 15:17:52

2

如果您在Python 3现在仍想知道插座,这里是使用它们的基本途径:

server.py

import time 
import socket 

# creating a socket object 
s = socket.socket(socket.AF_INET, 
        socket.SOCK_STREAM) 

# get local Host machine name 
host = socket.gethostname() # or just use (host == '') 
port = 9999 

# bind to pot 
s.bind((host, port)) 

# Que up to 5 requests 
s.listen(5) 

while True: 
    # establish connection 
    clientSocket, addr = s.accept() 
    print("got a connection from %s" % str(addr)) 
    currentTime = time.ctime(time.time()) + "\r\n" 
    clientSocket.send(currentTime.encode('ascii')) 
    clientSocket.close() 

客户端。PY

import socket 

# creates socket object 
s = socket.socket(socket.AF_INET, 
        socket.SOCK_STREAM) 

host = socket.gethostname() # or just use (host = '') 
port = 9999 

s.connect((host, port)) 

tm = s.recv(1024) # msg can only be 1024 bytes long 

s.close() 
print("the time we got from the server is %s" % tm.decode('ascii')) 

运行server.py第一,然后运行client.py

这仅仅是接收和发送currentTime的。

Python 3.4套接字有什么新内容?

python 2.7 sockets和python 3.4 sockets之间的主要区别是发送消息。你必须.encode()(通常使用“ASCII”或空白作为参数/参数) ,然后使用.decode()

例如使用.encode()发送,并使用.decode()接收。

附加信息:client/server socket tutorial