Eine TCP sockets library für (aktuell) Haskell und Python
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

134 linhas
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)