Eine TCP sockets library für (aktuell) Haskell und Python
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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