2011-01-09 18 views
6

Estoy trabajando en un poco de un proyecto en python. Tengo un cliente y un servidor. El servidor escucha las conexiones y una vez que se recibe una conexión espera la entrada del cliente. La idea es que el cliente pueda conectarse al servidor y ejecutar comandos del sistema como ls y cat. Este es mi código de servidor:Python cliente/servidor pregunta

import sys, os, socket 


host = ''     
port = 50105 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.bind((host, port)) 
print("Server started on port: ", port) 

s.listen(5) 
print("Server listening\n") 
conn, addr = s.accept() 
print 'New connection from ', addr 
while (1): 
    rc = conn.recv(5) 
    pipe = os.popen(rc) 
    rl = pipe.readlines() 
    file = conn.makefile('w', 0) 
    file.writelines(rl[:-1]) 
    file.close() 
    conn.close() 

Y este es mi código de cliente:

import sys, socket 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
host = 'localhost' 
port = input('Port: ') 
s.connect((host, port)) 
cmd = raw_input('$ ') 
s.send(cmd) 
file = s.makefile('r', 0) 
sys.stdout.writelines(file.readlines()) 

Cuando inicio el servidor consigo la salida derecha, diciendo que el servidor está escuchando. Pero cuando me conecto con mi cliente y escriba un comando que el servidor finaliza con este error:

Traceback (most recent call last): 
File "server.py", line 21, in <module> 
    rc = conn.recv(2) 
File "/usr/lib/python2.6/socket.py", line 165, in _dummy 
    raise error(EBADF, 'Bad file descriptor') 
socket.error: [Errno 9] Bad file descriptor 

En el lado del cliente, consigo la salida de ls pero el servidor se fastidien.

+1

Entonces, ¿qué es tu pregunta? –

+0

¿Cómo puedo hacerlo para que el cliente permanezca abierto para que se emitan más comandos? Para que el cliente pueda seguir ingresando comandos y se ejecuten en el servidor. – AustinM

+1

Parece que estás reinventando ssh, ¿por qué? – nosklo

Respuesta

6

el código llama conn.close() y luego vuelve de nuevo en torno a conn.recv(), pero conn ya está cerrado.

+0

Tomé conn.close() fuera del servidor y ahora cuando Escribo un comando en el cliente que simplemente cuelga. No pasa nada. – AustinM

+0

En ese caso, su 'file.readlines()' en el cliente está esperando que el servidor envíe algo más (porque podría). Tendrá que decidir: ¿quiere que su servidor acepte un comando y luego cierre la conexión, o quiere que el servidor envíe algo que indique que la salida del comando se ha completado? Si es este último, ¿qué le gustaría enviar? –

+0

Bueno, quiero que el servidor envíe algo que indique que la salida del comando se ha completado. La idea es que el servidor siga escuchando las conexiones y el cliente pueda ingresar un comando, obtener el resultado y luego ingresar más comandos si el usuario lo desea. – AustinM

3

Si desea que su cliente para repetir lo que está haciendo, sólo tiene que añadir un bucle de allí;)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
host = 'localhost' 
port = input('Port: ') 
s.connect((host, port)) 
while True: 
    cmd = raw_input('$ ') 
    s.send(cmd) 
    file = s.makefile('r', 0) 
    sys.stdout.writelines(file.readlines()) 

probablemente debería estar más cerca de lo que desea.

Otros comentarios:

s.listen(1) 

Esta declaración probablemente se debe mover fuera del bucle while. Solo necesita llamar al listen una vez.

pipe = os.popen(rc) 

os.popen ya no se utiliza, utilice el subprocess module lugar.

file = s.makefile('r', 0) 

Está abriendo un archivo, pero nunca se cierra el archivo. Probablemente debería agregar un file.close() después de su llamada sys.stdout.writelines().

EDITAR: responder a las siguientes observaciones; hecho aquí debido a la longitud y formateo

Tal como está, se lee desde el socket una vez, y luego se cierra inmediatamente. Por lo tanto, cuando el cliente va a enviar el siguiente comando, ve que el servidor cerró el socket e indica un error.

La solución es cambiar el código del servidor para que pueda manejar la recepción de varios comandos. Tenga en cuenta que esto se resuelve introduciendo otro ciclo.

Usted necesita para envolver

rc = conn.recv(2) 
pipe = os.popen(rc) 
rl = pipe.readlines() 
fl = conn.makefile('w', 0) 
fl.writelines(rl[:-1]) 

en otro bucle while True: para que se repite hasta que el cliente se desconecta, y luego envolver en un intento de que, salvo el bloque que llama la IOError que se produce por conn.recv () cuando el cliente se desconecta.

el try-excepto bloque debe ser similar

try: 
    # the described above loop goes here 
except IOError: 
    conn.close() 
# execution continues on... 
+0

Bueno, el bucle funciona muy bien ya que una vez que se ingresa un comando, se ejecuta en la máquina del servidor, obtengo el resultado en mi máquina cliente y luego obtengo el ' $ 'preguntar de nuevo. La cuestión es que después de eso, cuando escribo otro comando, no pasa nada. Entonces, si intento otro comando me sale un error socket.error: [Errno 32] Broken pipe – AustinM

+0

Hm interesting. Ahora el cliente simplemente se cuelga y no obtengo el resultado del comando hasta que el servidor se cierra. – AustinM

+0

Cambiando 'fl = conn.makefile ('w', 0)' a 'fl = conn.makefile ('w')' lo arregló por mí. Establecer el segundo argumento, que es un tamaño de búfer, a 0 parecía no funcionar tan bien. –