elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


 


Tema destacado:


+  Foro de elhacker.net
|-+  Programación
| |-+  Scripting
| | |-+  [RESUELTO] ejecutar recv() temporalmente | Python3 sockets
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [RESUELTO] ejecutar recv() temporalmente | Python3 sockets  (Leído 585 veces)
Drakaris

Desconectado Desconectado

Mensajes: 222


Todo lo que puedas imaginar, lo puedes crear.


Ver Perfil
[RESUELTO] ejecutar recv() temporalmente | Python3 sockets
« en: 11 Agosto 2020, 13:16 »

RESUELTO

El resultado fue crear en el cliente un nuevo subproceso donde este en escucha a la respuesta del mensaje OK o TooManyClients, y con cuya respuesta guardarla en un booleano en la clase Globals y con ello hacer el condicional.

Y en el servidor cuando se conecta un cliente almacena en la lista  list_clients, creada en la clase Globals, una sublista con el nombre del cliente "SockServicesX", la conexion, y el booleano (por defecto False).
Más tarde creo la clase Select_user que es para seleccionar la sublista correspondiente al cliente conectado y con ello usar esa información para eliminar el usuario (sublista) con user.remove_client() o check la conexión user.check(conn)


Dejo el código en el proximo post

En conclusión no puede haber dos funciones recv() en una misma conexion socket

Buenas, estoy haciendo una conexion socket con varios clientes... con un máximo de 3 clientes. La idea es
 la siguiente:

socket server completo
Código
  1. #!/usr/bin/python3
  2. # Server
  3. import socket, threading, os, sys, time
  4.  
  5. # globals variables
  6. class globals:
  7. PORT, NUMBER_CONNECTIONS = 2048, 3 #constants
  8. number_client = 0 # count clients number
  9.  
  10. ### CONNECTIONS CLIENTS PARALLEL ###
  11.  
  12. def client(connection, address, idle):
  13.  
  14. ADDRESS_CLIENT, PORT_CLIENT = address[0], address[1]
  15.  
  16. print("client "+str(idle)+" ["+str(ADDRESS_CLIENT)+"] connected by "+str(PORT_CLIENT))
  17. while True:
  18. data = connection.recv(1024)
  19.  
  20. if data.decode() == "exit" or data.decode() == "close":
  21. connection.sendall(b"GoodBye")
  22. print("Client "+str(idle)+" ["+str(ADDRESS_CLIENT)+":"+str(PORT_CLIENT)+"] left")
  23. globals.number_client-=1 # subtract client at count
  24. break
  25. elif data.decode() == "KeyboardInterrupt":
  26. print("[\033[0;31m*\033[0m] Connection interrupted with Client "+str(idle))
  27. globals.number_client-=1 # subtract client at count
  28. break
  29. else:
  30. connection.sendall(data)
  31.  
  32. #close the connection with client
  33. connection.close()
  34.  
  35. ### MAIN ###
  36. try:
  37. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  38. sock.bind(("",globals.PORT))
  39. sock.listen(globals.NUMBER_CONNECTIONS)
  40. print("[\033[0;34m*\033[0m] Listening port "+str(globals.PORT)+"....")
  41. while True:
  42. conn, addr = sock.accept()
  43. # if he is fourth client o more, not connect it
  44. if not globals.number_client+1 > globals.NUMBER_CONNECTIONS:
  45. globals.number_client+=1 # add client at count
  46. idle="SockServices"+str(globals.number_client)
  47. socket_client = threading.Thread(target=client,name=idle,args=(conn, addr, idle))
  48. ;
  49. socket_client.start()
  50. else:
  51. conn.sendall(b"TooManyClients")
  52.  
  53. except KeyboardInterrupt:
  54. # close the server
  55. print("\n[\033[1;34m*\033[0m] Closing server....")
  56. sock.close()
  57. os.system("fuser -k -n tcp %s 2>&1" % globals.PORT)
  58.  

explicación

variables globales
Código
  1. # globals variables
  2. class globals:
  3. PORT, NUMBER_CONNECTIONS = 2048, 3 #constants
  4. number_client = 0 # count clients number
  5.  

Creo una conexion socket nomal. [globals es una clase con las variables que se van a utilizan en todo el script (también en dentro de funciones)]

Código
  1.  
  2. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  3. sock.bind(("",globals.PORT))
  4. sock.listen(globals.NUMBER_CONNECTIONS)
  5. print("[\033[0;34m*\033[0m] Listening port "+str(globals.PORT)+"....")
  6. while True:
  7. conn, addr = sock.accept()
  8. # if he is fourth client o more, not connect it
  9. if not globals.number_client+1 > globals.NUMBER_CONNECTIONS:
  10. globals.number_client+=1 # add client at count
  11. idle="SockServices"+str(globals.number_client)
  12. socket_client = threading.Thread(target=client,name=idle,args=(conn, addr, idle));
  13. socket_client.start()
  14. else:
  15. conn.sendall(b"TooManyClients")
  16.  

Cuando corre el bucle si es 1º,2º o 3º cliente la variable globals.number_client con valor por defecto 0 es incrementado, y creo una idle que es el nombre SockServices mas el numero de cliente, después creo un hilo con nombre SockServices donde va a ejecutar la funcion client

Código:
if not globals.number_client+1 > globals.NUMBER_CONNECTIONS:
globals.number_client+=1 # add client at count
idle="SockServices"+str(globals.number_client)
socket_client = threading.Thread(target=client,name=idle,args=(conn, addr, idle));
socket_client.start()

Si la condición no se cumple, significa que ya hay tres clientes y me envias al cliente con conexion denegada la palabra "TooManyClients"

Código
  1. else:
  2. conn.sendall(b"TooManyClients")
  3.  

socket client completo

Código
  1. #!/usr/bin/python3
  2. #client
  3. import socket, time, os, sys
  4.  
  5. # CONSTANTS
  6. ADDRESS, PORT = "127.0.0.1", 2048
  7.  
  8. sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  9. sock.connect((ADDRESS, PORT))
  10. sock.settimeout(3)
  11.  
  12. while True:
  13. try:
  14. try:
  15. #receive server's data
  16. check = sock.recv(1024)
  17. except socket.timeout:
  18. pass
  19.  
  20. if check.decode() == "TooManyClients":
  21. print("[\033[0;31m*\033[0m] Too many clients connected")
  22. sock.close()
  23. sys.exit()
  24. else:
  25. print("[\033[0;32m*\033[0m] Connection established")
  26. pass
  27.  
  28. sock.setblocking(s)
  29. while True:
  30. #prompt terminal
  31. prompt = input("> ")
  32.  
  33. #receive server's data
  34. data = sock.recv(1024)
  35.  
  36. print(data.decode())
  37.  
  38. #Send prompt's data to server
  39. sock.sendall(prompt.encode())
  40.  
  41. if data.decode() == "GoodBye":
  42. print("[\033[0;34m*\033[0m] Closing connection....")
  43. break
  44. except KeyboardInterrupt:
  45. sock.sendall(b"KeyboardInterrupt")
  46. print("\n[\033[0;31m*\033[0m] Connection interrupted, closing connection....")
  47. break
  48. sock.close()
  49.  

explicación

Creo una conexion socket normal y me conecto al servidor

Código
  1. # CONSTANTS
  2. ADDRESS, PORT = "127.0.0.1", 2048
  3.  
  4. sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  5. sock.connect((ADDRESS, PORT))
  6.  

Una vez hecha la conexion ejecuto el primer bucle while True, que lo ejecuto para saber si el cliente se puede conectar o no.
Primero recibo los datos del servidor

Código
  1. while True:
  2. try:
  3. #receive server's data
  4. data = sock.recv(1024)
  5.  

Sí lo que recibo es TooManyClients, le digo al cliente que no se puede conectar porque el foro de clientes está completo y cierro la conexion

Código
  1. if data.decode() == "TooManyClients":
  2. print("[\033[0;31m*\033[0m] Too many clients connected")
  3. sock.close()
  4. sys.exit()
  5.  

Si no recibo nada imprime que esto conectado al servidor y ejecuta el siguiente bucle.

Código
  1. else:
  2. print("[\033[0;32m*\033[0m] Connection established")
  3. pass
  4. while True:
  5. #prompt terminal
  6. prompt = input("> ")
  7.  
  8. print(data.decode())
  9.  
  10. #Send prompt's data to server
  11. sock.sendall(prompt.encode())
  12.  
  13. if data.decode() == "GoodBye":
  14. print("[\033[0;34m*\033[0m] Closing connection....")
  15. break
  16.  

Que el siguiente bucle ya podré enviar datos al servidor

problema

Como podeis ver en la imagen cuando me conecto, no me imprime el mensaje Connection establlished, sino que se queda como en escucha, en el cuarto intento de conexión (cuadro izquierdo abajo), me imprime el mensaje Too many clients connected

Creo que el problema esta en el lado cliente, en el primer while True, que esta recibiendo los datos

Código
  1. sock.connect((ADDRESS, PORT))
  2. while True:
  3. try:
  4. #receive server's data
  5. data = sock.recv(1024)
  6.  

El problema es que el recv() se queda en escucha y como no recibe nada... ya que el condicional if que valida el usuario en socket server no envia nada al cliente.

Código
  1. if not globals.number_client+1 > globals.NUMBER_CONNECTIONS:
  2. globals.number_client+=1 # add client at count
  3. idle="SockServices"+str(globals.number_client)
  4. socket_client = threading.Thread(target=client,name=idle,args=(conn, addr, idle));
  5. socket_client.start()
  6. else:
  7. conn.sendall(b"TooManyClients")
  8.  


Sí en la condicional if le envio un OK, y con esto, se me inicia pero si envio algo del cliente al servidor siempre me recibe el mensaje OK, y no GoodBye

Código
  1. if not globals.number_client+1 > globals.NUMBER_CONNECTIONS:
  2.                        conn.sendall(b"OK")
  3. globals.number_client+=1 # add client at count
  4. idle="SockServices"+str(globals.number_client)
  5. socket_client = threading.Thread(target=client,name=idle,args=(conn, addr, idle));
  6. socket_client.start()
  7. else:
  8. conn.sendall(b"TooManyClients")
  9.  


Como la idea de enviar el mensaje OK no funciona... me preguntaria si se podría en el cliente dejar de escuchar los datos a recibir recv(), hacer la condicional y después volver a escuchar los datos.. Se puede hacer esto con sock.setblocking()?
Código
  1. while True:
  2. try:
  3. #receive server's data
  4. data = sock.recv(1024)
  5. if data.decode() == "TooManyClients":
  6. print("[\033[0;31m*\033[0m] Too many clients connected")
  7. sock.close()
  8. sys.exit()
  9. else:
  10. print("[\033[0;32m*\033[0m] Connection established")
  11. pass
  12.  

Leí un post en stackoverflow, donde preguntaba como podía recibir datos con recv() un tiempo con select
https://stackoverflow.com/questions/2719017/how-to-set-timeout-on-pythons-socket-recv-method#answer-2721734

Yo lo que hice es lo siguiente:

importe el modulo select
Código
  1. import select

dentro del bucle cree una variable ready que le permite escuchar el rec() solo 2 segundos y cuando acabe estos segundos. Mientras pasa estos dos segundos, recibo los datos en la variable data y si data contiene TooManyClients la varibale booleana es False (por defecto es True).

Si la variable es True ejecutaré el pass y pasará al siguiente while y si es False me imprimira que hay demasiados clientes.

Código
  1. sock.setblocking(0)
  2. check = True
  3. while True:
  4. try:
  5. ready = select.select([sock], [],  [], 2)
  6. if ready[0]:
  7. #receive server's data
  8. data = sock.recv(1024)
  9. if data.decode() == "TooManyClients":
  10. check=False
  11. if check==False:
  12. print("[\033[0;31m*\033[0m] Too many clients connected")
  13. sock.close()
  14. sys.exit()
  15. else:
  16. print("[\033[0;32m*\033[0m] Connection established")
  17. pass
  18.  

Pero tengo dos problemas con esta solucion
  • Este script se ejecutará en sistemas Windows y Linux y en Windows el modulo select no funcionara
  • Cuando estoy ya conectado al servidor y envio un dato, este no me leé la variable data

Se puede en:

Código
  1. else:
  2. print("[\033[0;32m*\033[0m] Connection established")
  3. pass
  4.  
o en:
Código
  1. while True:
  2. #prompt terminal
  3. prompt = input("> ")
  4.  
  5. print(data.decode())
  6.  
  7. #Send prompt's data to server
  8. sock.sendall(prompt.encode())
  9.  
  10.  

Volver a activar el recv()? Y si se puede como?



actualizado

Buenas como mi idea es que recv() se ejecute temporalmente en el primer while True del cliente inserte lo siguiente:

Código
  1. sock.connect(...)
  2. sock.settimeout(3)
  3.  
  4. while True:
  5. try:
  6. try:
  7. #receive server's data
  8. check = sock.recv(1024)
  9. except socket.timeout:
  10. pass
  11.  

Durante 3 segundos me ejecuta el sock.recv() y cuando pasa el tiempo me salta la excepcion por la cual pasa al siguiente bucle, el problema esta en que lo que obtuve de recv() lo quisiera almacenar en una variable, teoricamente en check, pero cuando hago las condicionales check.decode() no me detecta cuya variable

Citar
Services
Traceback (most recent call last):
  File "./SockServices", line 16, in <module>
    check = sock.recv(1024)
socket.timeout: timed out

During handling of the above exception, another exception occurred:                                    

Traceback (most recent call last):
  File "./SockServices", line 18, in <module>
    print(check.decode())


« Última modificación: 16 Agosto 2020, 15:14 por Drakaris » En línea

Drakaris

Desconectado Desconectado

Mensajes: 222


Todo lo que puedas imaginar, lo puedes crear.


Ver Perfil
Re: [RESULTO] recv() settimeout, como guardarlo en una variable | Python3 sockets
« Respuesta #1 en: 14 Agosto 2020, 16:39 »

RESULTADO

servidor

Código
  1. #!/usr/bin/python3
  2. # Server
  3. import socket, threading, os, sys, time
  4.  
  5. # globals variables
  6. class Globals:
  7. PORT, NUMBER_CONNECTIONS = 2048, 3 #constants
  8. number_client = 0 # count clients number
  9. list_clients=[]
  10.  
  11. # select user's sublist and your index, for later use it
  12. class Select_user:
  13. def __init__(self, idle, port):
  14. for client in Globals.list_clients:
  15. index = Globals.list_clients.index(client)
  16. name_user = Globals.list_clients[index][0]
  17. port_user = Globals.list_clients[index][1][1]
  18. if name_user == idle and port_user == port:
  19. self.index_user = index
  20. self.user = Globals.list_clients[self.index_user]
  21.  
  22. def remove_client(self):
  23. del Globals.list_clients[self.index_user]
  24.  
  25. # If the third element of list clients is False, it means that the user is not checked
  26. def check(self, conn):
  27. if Globals.list_clients[self.index_user][2] == False:
  28. conn.send(b"OK")
  29. Globals.list_clients[self.index_user][2] = True
  30.  
  31. ### CONNECTIONS CLIENTS PARALLEL ###
  32.  
  33. def client(connection, address, idle):
  34. ADDRESS_CLIENT, PORT_CLIENT = address[0], address[1]
  35.  
  36. user = Select_user(idle, PORT_CLIENT)
  37. user.check(connection)
  38.  
  39. print("client "+str(idle)+" ["+str(ADDRESS_CLIENT)+"] connected by "+str(PORT_CLIENT))
  40. while True:
  41. data = connection.recv(1024)
  42.  
  43. if data.decode() == "exit" or data.decode() == "close":
  44. connection.sendall(b"GoodBye")
  45. print("Client "+str(idle)+" ["+str(ADDRESS_CLIENT)+":"+str(PORT_CLIENT)+"] left")
  46. Globals.number_client-=1 # subtract client at count
  47.  
  48. # delete user of list clients
  49. user = Select_user(idle, PORT_CLIENT)
  50. user.remove_client()
  51. break
  52. elif data.decode() == "KeyboardInterrupt":
  53. print("[\033[0;31m*\033[0m] Connection interrupted with Client "+str(idle)+" ["+str(ADDRESS_CLIENT)+":"+str(PORT_CLIENT)+"]")
  54. Globals.number_client-=1 # subtract client at count
  55.  
  56. # delete user of list clients
  57. user = Select_user(idle, PORT_CLIENT)
  58. user.remove_client()
  59. break
  60. else:
  61. connection.sendall(data)
  62.  
  63. #close the connection with client
  64. connection.close()
  65.  
  66. ### MAIN ###
  67. try:
  68. sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  69. sock.bind(("",Globals.PORT))
  70. sock.listen(Globals.NUMBER_CONNECTIONS)
  71. print("[\033[0;34m*\033[0m] Listening port "+str(Globals.PORT)+"....")
  72. while True:
  73. conn, addr = sock.accept()
  74. # if he is fourth client or higher, not connect it
  75. if not Globals.number_client+1 > Globals.NUMBER_CONNECTIONS:
  76. Globals.number_client+=1 # add client at count
  77. idle="SockServices"+str(Globals.number_client)
  78. Globals.list_clients.append([idle,addr,False]) # add client to list clients
  79. socket_client = threading.Thread(target=client,name=idle,args=(conn, addr, idle));
  80. socket_client.start()
  81. else:
  82. conn.sendall(b"TooManyClients")
  83.  
  84. except KeyboardInterrupt:
  85. # close the server
  86. print("\n[\033[1;34m*\033[0m] Closing server....")
  87. sock.close()
  88. os.system("fuser -k -n tcp %s 2>&1" % Globals.PORT)
  89.  

cliente

Código
  1. #!/usr/bin/python3
  2. #client
  3. import socket, time, os, sys, threading
  4.  
  5. # CONSTANTS
  6. class Globals:
  7. ADDRESS, PORT, CHECK = "127.0.0.1", 2048, None
  8.  
  9. def checking(sock):
  10. while True:
  11. check = sock.recv(1024)
  12. if check.decode() == "TooManyClients":
  13. Globals.CHECK = False
  14. elif check.decode() == "OK":
  15. Globals.CHECK = True
  16. break
  17.  
  18. sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
  19. sock.connect((Globals.ADDRESS, Globals.PORT))
  20.  
  21. while True:
  22. try:
  23. # Before, we check if the server allow us connect
  24. check = threading.Thread(target=checking, name="check_connection", args=(sock, ))
  25. check.start()
  26. sys.stdout.write("[\033[0;34m*\033[0m] Checking....")
  27. """After of run the thread, the program wait 3 seconds for receive the server's response
  28. and continue"""
  29. time.sleep(3)
  30.  
  31. if Globals.CHECK == False:
  32. print("[\033[0;31m*\033[0m] Too many clients connected")
  33. sock.close()
  34. sys.exit()
  35. else:
  36. print("[\033[0;32m*\033[0m] Connection established")
  37. pass
  38. while True:
  39.  
  40. #prompt terminal
  41. prompt = input("> ")
  42.  
  43. #Send prompt's data to server
  44. if prompt != "":
  45. sock.sendall(prompt.encode())
  46. else:
  47. continue
  48.  
  49. #receive server's data
  50. data = sock.recv(1024)
  51.  
  52. if data.decode() == "GoodBye":
  53. print("[\033[0;34m*\033[0m] Closing connection....")
  54. break
  55. else:
  56. print(data.decode())
  57. break
  58. except KeyboardInterrupt:
  59. sock.sendall(b"KeyboardInterrupt")
  60. print("\n[\033[0;31m*\033[0m] Connection interrupted, closing connection....")
  61. break
  62. sock.close()
  63.  


« Última modificación: 16 Agosto 2020, 15:15 por Drakaris » En línea

Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines