Eine TCP sockets library für (aktuell) Haskell und Python
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

134 líneas
4.1KB

  1. import socket
  2. import struct
  3. import ssl
  4. from threading import Thread
  5. import select
  6. class SocketClient:
  7. NO_BUFFERING = 0
  8. LENGTH_BUFFERING = 1
  9. DELIMITER_BUFFERING = 2
  10. def __init__(self, ssl_cert=None, buffering=LENGTH_BUFFERING,
  11. delimiter='\n'):
  12. self.terminated = False
  13. self.connected = False
  14. self.ssl_cert = ssl_cert
  15. self.buffering = buffering
  16. self.delimiter = delimiter
  17. self.left = b''
  18. print("Initialized socket client")
  19. def connect(self, host, port):
  20. try:
  21. self.socket = socket.socket()
  22. # if using a ssl certificate, wrap the socket using ssl
  23. if self.ssl_cert:
  24. self.socket = ssl.wrap_socket(self.socket,
  25. ca_certs=self.ssl_cert,
  26. cert_reqs=ssl.CERT_REQUIRED)
  27. self.socket.connect((host, port))
  28. self.connected = True
  29. return True
  30. except socket.error:
  31. print("ERROR: Error while connecting!")
  32. self.connected = False
  33. return False
  34. def start(self):
  35. print("Client has started")
  36. Thread(target=self.handle_server).start()
  37. def disconnect(self):
  38. print("disconnecting")
  39. self.connected = False
  40. self.send("quit")
  41. self.terminated = True
  42. self.socket.close()
  43. def send(self, data):
  44. try:
  45. if self.buffering is SocketClient.DELIMITER_BUFFERING:
  46. msg = (data + self.delimiter).encode()
  47. elif self.buffering is SocketClient.LENGTH_BUFFERING:
  48. msg = struct.pack('>I', len(data)) + data.encode()
  49. else:
  50. msg = data.encode()
  51. self.socket.sendall(msg)
  52. except Exception as e:
  53. print("ERROR: Error while sending", e)
  54. def handle_server(self):
  55. while not self.terminated:
  56. try:
  57. read_sockets, write_sockets, in_error = \
  58. select.select([self.socket, ], [self.socket, ], [], 5)
  59. except select.error:
  60. print("FATAL ERROR: Connection error")
  61. self.socket.shutdown(2)
  62. self.socket.close()
  63. if len(read_sockets) > 0:
  64. if self.buffering is SocketClient.DELIMITER_BUFFERING:
  65. recv, self.left = recvuntil(self.socket, self.delimiter,
  66. self.left)
  67. elif self.buffering is SocketClient.LENGTH_BUFFERING:
  68. raw_msglen = recvall(self.socket, 4)
  69. if not raw_msglen:
  70. print("Connection closed")
  71. self.on_quit()
  72. return None
  73. msglen = struct.unpack('>I', raw_msglen)[0]
  74. recv = recvall(self.socket, msglen)
  75. elif self.buffering is SocketClient.NO_BUFFERING:
  76. recv = self.socket.recv(2048)
  77. if len(recv) > 0:
  78. reply = self.on_receive(recv)
  79. if len(write_sockets) > 0 and reply:
  80. self.socket.send(reply)
  81. print("finished handling server")
  82. def on_receive(self, query):
  83. pass
  84. def on_quit(self):
  85. pass
  86. def recvall(sock, n):
  87. data = b''
  88. while len(data) < n:
  89. packet = sock.recv(n - len(data))
  90. if not packet:
  91. return None
  92. data += packet
  93. return data
  94. def recvuntil(sock, delimiter, left_over):
  95. data = left_over
  96. left = b''
  97. while True:
  98. packet = sock.recv(512)
  99. if not packet:
  100. return None
  101. data += packet
  102. idx = data.find(delimiter.encode())
  103. if idx >= 0:
  104. data = data[:idx]
  105. left = data[idx+len(delimiter):]
  106. break
  107. return data, left
  108. if __name__ == '__main__':
  109. client = SocketClient(buffering=SocketClient.DELIMITER_BUFFERING,
  110. delimiter='\r\n')
  111. client.connect('localhost', 4242)
  112. client.start()
  113. client.on_receive = lambda x: print("-->", x)
  114. while True:
  115. x = input("> ")
  116. client.send(x)