2013-04-07 13 views
10

wszystkich poniżej wymienionych jest na Windows maszyn przy użyciu Pythona 2.7Python Socket Słuchanie

Witam,

Jestem obecnie próbuje słuchać na gnieździe do przesyłu danych za pomocą zdalnego programu. Dane te są następnie drukowane na ekranie i wymagane jest wprowadzenie danych użytkownika, które następnie są zwracane do zdalnego programu. Podczas testów zdołałem wysłać do mnie program z programami wiersza poleceń (cmd, ipconfig, whoami, ftp), a następnie mój program zwraca z numerem jako wyborem opcji menu.

Zdalny program odbiera moją odpowiedź i wysyła dane wyjściowe wybranego polecenia. ipconfig i whoami działają doskonale, ale cmd i ftp tylko raz zwracają dane wyjściowe terminala. (To mogę wprowadzić jedną komendę do programu FTP i wyślij że zbyt zdalnego programu zanim nie słyszę z tyłu)

Część mojego kodu, która nie jest if ready[0]: nigdy nie staje się gotowy po raz drugi po pierwszej rozmowie.

Wiem, że program zdalny działa poprawnie, ponieważ mogę używać netcata do działania zamiast kodu i obsługiwać terminalu cmd w nieskończoność.

Jak mogę poprawnie wdrożyć nasłuchiwacz gniazda Pythona, który może uwzględniać ten typ połączenia?

Moje „program” w całości:

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) 

Proszę dać mi znać, jeśli potrzebujesz więcej informacji, każda pomoc będzie mile widziana, jestem bardzo nowy w tym i chętny do nauki.

+2

Czy próbowałeś za pomocą klasy "SocketServer"? Jest dobrze udokumentowany i wydaje się łatwiejszy w użyciu niż "gniazdo" (i może być również używany do słuchania): http://docs.python.org/2/library/socketserver.html – halflings

+0

jest to zbyt skomplikowane, co czy próbujesz osiągnąć? – tomasz

Odpowiedz

12

Zabawa z tym przez jakiś czas w końcu sprawdziła się dobrze z sesją telnetową lokalnie używając Pythona 2.7.

Co to jest, ustawia wątek, który działa, gdy klient łączy się ze słuchaniem dla rzeczy klienta.

Kiedy klient wysyła zwrot ("\ r \ n" może to zmienić, jeśli wchodzisz w interakcję z systemem Linux?), Komunikat zostanie wydrukowany na serwerze, a dzieje się tak, jeśli istnieje surowy wpis strona serwera zostanie wysłana do klienta:

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

Powyższa odpowiedź nie będzie działać dla więcej niż jednego połączenia. Zaktualizowałem go, dodając kolejny wątek do wykonywania połączeń. Teraz można połączyć więcej niż jednego użytkownika.

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

Klienci nie są w stanie zobaczyć, co mówią inni klienci, wiadomości z serwera będą wysyłane do wszystkich klientów. Zostawię to jako ćwiczenie dla czytelnika.

+0

Po prostu nie interesuje Cię, kiedy na tym samym komputerze i masz uruchomiony powyższy skrypt Pythona, po otwarciu okna CMD i wpisaniu telnet localhost 50000, po wpisaniu Hello i naciśnięciu Enter nic się nie dzieje. Czy wiesz, jak przeciągnąć łańcuch kończący z sesji Telnet systemu Windows? – Bertie

+0

Właśnie uruchomiłem skrypt w sesji systemu Windows, po naciśnięciu klawisza Enter na ekranie telnetu komunikat hello jest drukowany w cmd, który uruchamia skrypt. Czego się spodziewasz? – Noelkd

+0

Zaczynałem program przez IPython, ponieważ używam Anacondy (i Spyder IDE). Wygląda na to, że po uruchomieniu programu przy użyciu konsoli Python, działa i widzę, że telnet jest wyświetlany w programie Python. Jedyny problem polega na tym, że jeśli spróbuję wykonać drugie połączenie z innego komputera w sieci w tym samym czasie, nie łączy się? Wiesz dlaczego? – Bertie

2

Jeśli jesteś w Pythonie 3 teraz i nadal zastanawiać gniazd, tutaj jest podstawowym sposobem korzystania z nich:

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

klient.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')) 

Run server.py pierwszy, a następnie uruchomić client.py

To tylko odbierać i wysyłać CurrentTime.

Co nowego w gniazdach Pythona 3.4?

Główna różnica między gniazdami Pythona 2.7 a gniazdami Pythona 3.4 to wiadomości wysyłane. trzeba .encode() (zazwyczaj przy użyciu „ascii” lub puste jako parametry/Argumenty) a następnie przy użyciu .decode()

Na przykład użyć .encode() wysłać i używać .decode() otrzymać.

Dodatkowe info: client/server socket tutorial