-
Notifications
You must be signed in to change notification settings - Fork 0
/
server_basic.py
126 lines (89 loc) · 4.13 KB
/
server_basic.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import socket
import pickle
import struct
import cv2
from threading import Thread # Imports Thread
from constants import * # Import all constants and functions in constants.py
from client_thread import ClientThread # Imports ClientThread
SERVER_SOCKET = None # The server socket object
PI_CLIENT = None # The client connection object
PI_CLIENT_CONNECTED = False # Whether the client is connected or not
RUNNING = True # Whether the server is running, Main Boolean
def handle_connection (connection, address):
''' Handle clients trying to connect to the server '''
global PI_CLIENT
global PI_CLIENT_CONNECTED
PRINT('Handling connection from ' + ENC_VALUE(address[0]) + '...', INFO)
# Create a new client thread for the incoming client
PI_CLIENT = ClientThread()
PI_CLIENT_CONNECTED = True
try:
PRINT('Starting client thread for ' + ENC_VALUE(address[0]) + '...', INFO)
# Create a thread for the client's run method (to send and recieve data)
client_thread = Thread(target=PI_CLIENT.run, args=(connection, address))
client_thread.start() # Starts client_thread
client_thread.join() # Wait for the client to disconnect
PRINT('Disconnected from ' + ENC_VALUE(address[0]) + '.', INFO)
# Reset client variables
connection.close() # Ends connection
PI_CLIENT = None
PI_CLIENT_CONNECTED = False
except Exception as e: # Prints Error
PRINT('Could not run client for ' + ENC_VALUE(address[0]) + '.', ERROR)
PRINT('| ' + str(e), ERROR)
def connection_listener ():
''' Listens for incoming clients that want to connect to the server '''
global RUNNING
global SERVER_SOCKET
# Create socket object
SERVER_SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SERVER_SOCKET.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
# Bind socket to a specific port
SERVER_SOCKET.bind(('', PORT))
PRINT('Socket bound to port ' + ENC_VALUE(PORT) + '.', SUCCESS)
except socket.error as err: # Prints Error
PRINT('Socket failed to bind to port ' + ENC_VALUE(PORT) + '.', ERROR)
PRINT('| ' + err, ERROR)
PRINT('Listening for connections...', INFO)
# Start listening for connections
SERVER_SOCKET.listen(1)
while RUNNING:
try:
# If a client connects, get the connection object and the address
conn, address = SERVER_SOCKET.accept()
conn.settimeout(TIMEOUT) # Timeout for connection
# Start a connection handler thread to begin reading and writing data
connection_thread = Thread(target=handle_connection, args=(conn, address))
connection_thread.start() # Starts connection_thread
connection_thread.join() # Wait for the connection to disconnect
except:
pass
SERVER_SOCKET.close() # Closes server socket
PRINT('Socket closed.', SUCCESS)
def main ():
''' The main method :o '''
global PI_CLIENT
global PI_CLIENT_CONNECTED
global RUNNING
# Create thread for the connection handler loop
connection_handler = Thread(target=connection_listener, args=())
connection_handler.start() # Start connection_handler thread
while RUNNING: # Main loop
if PI_CLIENT_CONNECTED:
try:
# Get the video frame from the client and decode it
frame = cv2.imdecode(PI_CLIENT.recv_data[DATA_IDX_VIDEO], cv2.IMREAD_COLOR)
# Display camera feed on 'frame'
cv2.imshow('frame', frame)
# If the 'q' key is pressed, shut down the server
if cv2.waitKey(1) & 0xFF == ord('q'):
PI_CLIENT.push_command(COMMAND_QUIT) # Sends quit command
RUNNING = False # Sets main boolean to false, ending Main loop
except:
pass
cv2.destroyAllWindows() # Closes all cv2 widows
connection_handler.join() # Ends connection
PRINT('Quit.', SUCCESS)
if __name__ == '__main__':
main()