2013-04-07 64 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