Прослушивание Socket Python
Все приведенное ниже относится к машинам Windows, использующим python 2.7
Здравствуйте,
В настоящее время я пытаюсь прослушивать сокет для отправки данных с помощью удаленной программы. Затем эти данные печатаются на экране, и запрашивается пользовательский ввод, который затем возвращается в удаленную программу. При тестировании я смог отправить удаленную программу мне меню программ командной строки (cmd, ipconfig, whoami, ftp), а затем моя программа вернется с номером в качестве выбора опции меню.
Удаленная программа получает мой ответ и отправляет вывод выбранной команды. ipconfig и whoami работают отлично, но cmd и ftp только возвращает вывод терминала один раз. (I.E. Я могу ввести одну команду в программу 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)
Пожалуйста, дайте мне знать, если вам нужна дополнительная информация, любая помощь будет очень признательна, я очень новичок в этом и хочу учиться.
Ответы
Ответ 1
Играя с этим на некоторое время, наконец, он хорошо работал с сеансом telnet локально, используя python 2.7.
Что он делает, так это настроить поток, который запускается, когда клиент подключается к прослушиванию клиентских файлов.
Когда клиент отправляет возврат ( "\ 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()
Клиенты не могут видеть, что говорят другие клиенты, сообщения от сервера будут отправляться всем клиентам. Я оставлю это как упражнение для читателя.
Ответ 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()
client.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
Это просто получение и отправка текущего времени.
Что нового в сокетах Python 3.4?
Основное различие между сокетами python 2.7 и сокетами python 3.4 - это отправляющие сообщения. вы должны .encode()
(обычно используя 'ascii' или blank как параметры/аргументы)
и затем используя .decode()
Например, используйте .encode()
для отправки и используйте .decode()
для получения.
Дополнительная информация: учебник для сокетов клиента/сервера