|
@@ -0,0 +1,89 @@
|
|
1
|
+#!/usr/bin/python3
|
|
2
|
+#-*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+#
|
|
5
|
+# A server that provide access to interactive python interpreter through network
|
|
6
|
+#
|
|
7
|
+# This is a demo implementation of a Lodel2 interface
|
|
8
|
+
|
|
9
|
+import socket
|
|
10
|
+import threading
|
|
11
|
+import subprocess
|
|
12
|
+import time
|
|
13
|
+import sys
|
|
14
|
+import signal
|
|
15
|
+
|
|
16
|
+PORT = 1337
|
|
17
|
+#BIND = None
|
|
18
|
+#BIND = 'localhost'
|
|
19
|
+BIND = '147.94.79.182'
|
|
20
|
+THREAD_COUNT = 10
|
|
21
|
+SOCK_TIMEOUT = 5
|
|
22
|
+
|
|
23
|
+servsock = None # Stores the server socket in order to close it when exception is raised
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+# Thread function called when client connected
|
|
27
|
+def client_thread(sock, addr):
|
|
28
|
+ # Starting interactive Lodel2 python in a subprocess
|
|
29
|
+ sock.setblocking(True)
|
|
30
|
+ sock_stdin = sock.makefile(mode='r', encoding='utf-8', newline="\n")
|
|
31
|
+ sock_stdout = sock.makefile(mode='w', encoding='utf-8', newline="\n")
|
|
32
|
+
|
|
33
|
+ ipy = subprocess.Popen(['python', 'netipy_loader.py', addr[0]], stdin=sock_stdin, stdout=sock_stdout, stderr=sock_stdout)
|
|
34
|
+ ipy.wait()
|
|
35
|
+ sock.close()
|
|
36
|
+ return True
|
|
37
|
+
|
|
38
|
+# Main loop
|
|
39
|
+def main():
|
|
40
|
+ servsock = socket.socket(family = socket.AF_INET, type=socket.SOCK_STREAM)
|
|
41
|
+ servsock.settimeout(5)
|
|
42
|
+ bind_addr = socket.gethostname() if BIND is None else BIND
|
|
43
|
+ servsock.bind((bind_addr, PORT))
|
|
44
|
+ servsock.listen(5)
|
|
45
|
+ globals()['servsock'] = servsock
|
|
46
|
+
|
|
47
|
+ threads = list()
|
|
48
|
+
|
|
49
|
+ print("Server listening on %s:%s" % (bind_addr, PORT))
|
|
50
|
+ while True:
|
|
51
|
+ # Accept if rooms left in threads list
|
|
52
|
+ if len(threads) < THREAD_COUNT:
|
|
53
|
+ try:
|
|
54
|
+ (clientsocket, addr) = servsock.accept()
|
|
55
|
+ print("Client connected : %s" % addr[0])
|
|
56
|
+ thread = threading.Thread(target = client_thread, kwargs = {'sock': clientsocket, 'addr': addr})
|
|
57
|
+ threads.append(thread)
|
|
58
|
+ thread.start()
|
|
59
|
+ except socket.timeout:
|
|
60
|
+ pass
|
|
61
|
+
|
|
62
|
+ # Thread cleanup
|
|
63
|
+ for i in range(len(threads)-1,-1,-1):
|
|
64
|
+ thread = threads[i]
|
|
65
|
+ thread.join(0.1) #useless ?
|
|
66
|
+ if not thread.is_alive():
|
|
67
|
+ print("Thread %d exited" % i)
|
|
68
|
+ threads.pop(i)
|
|
69
|
+
|
|
70
|
+# Signal handler designed to close socket when SIGINT
|
|
71
|
+def sigint_sock_close(signal, frame):
|
|
72
|
+ if globals()['servsock'] is not None:
|
|
73
|
+ globals()['servsock'].close()
|
|
74
|
+ print("\nCtrl+c pressed, exiting...")
|
|
75
|
+ exit(0)
|
|
76
|
+
|
|
77
|
+if __name__ == '__main__':
|
|
78
|
+ signal.signal(signal.SIGINT, sigint_sock_close)
|
|
79
|
+ try:
|
|
80
|
+ main()
|
|
81
|
+ except Exception as e:
|
|
82
|
+ if globals()['servsock'] is not None:
|
|
83
|
+ globals()['servsock'].close()
|
|
84
|
+ raise e
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|