-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.py
153 lines (118 loc) · 5.32 KB
/
server.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import socket
import threading
import datetime
import sys
from myconfig import ACK_KILL_PROCESS
from myconfig import UPTIME
from myconfig import REQNUM
from myconfig import CLOSE
from myconfig import TIMEOUT
from myconfig import TCP_UDP_PROTOCOL
# MARK: Global variables
requestsReceived = 0
serverStartedSince = datetime.datetime.now()
# MARK: Classes definitions
class ThreadedServer(object):
# MARK: Constructor
def __init__(self, ip, port):
self.ip = ip
self.port = port
# Get protocol according to TCP_UDP_PROTOCOL value
protocol = socket.SOCK_STREAM if TCP_UDP_PROTOCOL else socket.SOCK_DGRAM
try:
self.serverSocket = socket.socket(socket.AF_INET, protocol)
# [Errno 98] Address already in use
# the SO_REUSEADDR flag tells the kernel to reuse a local socket in TIME_WAIT state,
# without waiting for its natural timeout to expire.
self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
except socket.error as e:
print("Failed to create socket: %s"%(e))
sys.exit()
try:
self.serverSocket.bind((self.ip, self.port))
# Server's up
mode = "TCP" if TCP_UDP_PROTOCOL else "UDP"
print("Server is up and ready to receive connections in **%s MODE (change it inside myconfig.py file)**! IP %s and PORT %s"%(mode, self.ip, self.port))
except socket.error as e:
print("Failed to bind: %s"%(e))
sys.exit()
# MARK: Methods
def startTCPServer(self):
# Listen for connections made to the socket. The backlog argument specifies the maximum number of
# queued connections and should be at least 0; the maximum value is system-dependent (usually 5),
# the minimum value is forced to 0.
self.serverSocket.listen(5)
while True:
# Wait until a client connects
clientConnection, clientAddress = self.serverSocket.accept()
clientConnection.settimeout(60)
# Throw a thread in order to handle simultaneous clients
threading.Thread(target = self.handleTCPClientConnection,args = (clientConnection, clientAddress)).start()
def startUDPServer(self):
self.handleUDPClientConnection(self.serverSocket)
def handleTCPClientConnection(self, clientConnection, clientAddress):
print("Client connected from IP %s"%(clientAddress[0]))
# Stay in touch to client until he/she leaves
stayInTouch = True
while stayInTouch:
# Get client's message
messageFromClient = clientConnection.recv(4096)
if messageFromClient:
print("MESSAGE FROM IP %s: %s"%(clientAddress[0], messageFromClient))
try:
# Handle the message according to received signal and send a response to client
response = handleMessageAndGetResponse(messageFromClient)
except:
response = ACK_KILL_PROCESS
stayInTouch = False
# Reply client
clientConnection.send(response)
# Close connection when user sends a CLOSE signal
clientConnection.close()
print("Client disconnected from IP %s"%(clientAddress[0]))
def handleUDPClientConnection(self, serverSocket):
while True:
# Get client's message
messageFromClient, clientAddress = serverSocket.recvfrom(4096)
if messageFromClient:
print("MESSAGE FROM IP %s: %s"%(clientAddress[0], messageFromClient))
try:
# Handle the message according to received signal and send a response to client
response = handleMessageAndGetResponse(messageFromClient)
except:
response = ACK_KILL_PROCESS
# Reply client
serverSocket.sendto(response, clientAddress)
print("Client disconnected from IP %s"%(clientAddress[0]))
# MARK: Functions
def incrementNumberOfConnections():
# Increment number of received connections
global requestsReceived
requestsReceived += 1
def handleMessageAndGetResponse(message):
incrementNumberOfConnections()
if message == "\\CLOSE":
raise Exception("User's just closed connection.")
handler = {
UPTIME: "The server is running since %s. Total time up: %s"%(serverStartedSince, datetime.datetime.now() - serverStartedSince),
REQNUM: "Number of requests received, including this one: %s"%(requestsReceived)
}
return handler.get(message, "Invalid message: try '%s', '%s' or '%s"%(UPTIME, REQNUM, CLOSE))
# MARK: Init main()
def main():
while True:
try:
ip = raw_input("Enter an ip address to this server(Ex.: 'localhost', '127.0.0.1', ''): ")
port = int(raw_input("Enter a port: "))
ip = str(ip)
port = int(port)
if TCP_UDP_PROTOCOL:
ThreadedServer(ip ,port).startTCPServer()
else:
ThreadedServer(ip ,port).startUDPServer()
break
except ValueError:
pass
print("\n** Welcome to my socket app! Send a message using TCP/UDP sockets! Change protocol inside myconfig.py file **\n\n")
main()
print("** This is the end! **")