Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TCP_Server_thread_Stream.py
blob: 93cf2eeee2bf945060f56459053091a1d145599f (plain)
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#   TCP_Server_thread_Stream.py por:
#   Flavio Danesse <fdanesse@gmail.com>
#   CeibalJAM! - Uruguay - Plan Ceibal
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import time
import socket
import threading
import SocketServer

import time
from SocketServer import StreamRequestHandler
from SocketServer import ThreadingTCPServer

import Variables as ESPEJO

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.ThreadingTCPServer):
	''' Servidor Multihilo para conexiones simultáneas. '''
	pass
	'''   	
	__init__(self, server_address, RequestHandlerClass) from TCPServer
	fileno(self) from TCPServer
	finish_request(self, request, client_address) from TCPServer
	get_request(self) from TCPServer
	handle_error(self, request, client_address) from TCPServer
	handle_request(self) from TCPServer
	process_request(self, request, client_address) from ThreadingMixIn
	serve_forever(self) from TCPServer
	server_activate(self) from TCPServer
	server_bind(self) from TCPServer
	verify_request(self, request, client_address) from TCPServer
	'''
	'''
	def __init__(self, server_address, handler_class=None):
		SocketServer.TCPServer.__init__(self, server_address, handler_class)
		return

	def server_activate(self):
		SocketServer.TCPServer.server_activate(self)
		return

	def serve_forever(self):
		while True:
		    self.handle_request()
		return

	def handle_request(self):
		return SocketServer.TCPServer.handle_request(self)

	def verify_request(self, request, client_address):
		return SocketServer.TCPServer.verify_request(self, request, client_address)

	def process_request(self, request, client_address):
		return SocketServer.TCPServer.process_request(self, request, client_address)

	def server_close(self):
		return SocketServer.TCPServer.server_close(self)

	def finish_request(self, request, client_address):
		return SocketServer.TCPServer.finish_request(self, request, client_address)

	def close_request(self, request_address):
		return SocketServer.TCPServer.close_request(self, request_address) '''

class ThreadedTCPRequestHandler(SocketServer.StreamRequestHandler):
	''' Atiende y procesa todas las conexiones entrantes
	__del__(self) from BaseRequestHandler
	__init__(self, request, client_address, server) from BaseRequestHandler
	finish(self)
	handle(self) from BaseRequestHandler
	setup(self)
	def __init__(self, request, client_address, server):
		SocketServer.StreamRequestHandler.__init__(self, request, client_address, server)
		return '''

	def handle(self):
	# Acepta la conexión de un jugador
		while 1:
			try:
				datos = self.request.recv(200)
				self.recibir_datos(datos) 
				self.enviar_datos()

			except socket.error, e:
				print "Error en Handle del Server: ", "Error %s" % (e)
				self.request.close()
				return	

	def recibir_datos(self, datos):
	# Recibe los datos del jugador conectado
		mensajes = str(datos).split(ESPEJO.TERMINATOR)
		#print "Datos Recibidos en Servidor: ", mensajes

		for mensaje in mensajes:
			valores = mensaje.split()
			if "T" in valores:
			# Se recibe un tanque
				try:
				# para evitar que falle si no vienen todos los datos
					nombre, angulo, x, y = int(valores[0]), int(valores[2]), int(valores[3]), int(valores[4])
					self.procesar_datos_tanques(nombre=nombre, angulo=angulo, x=x, y=y)
				except:
					return

			elif "B" in valores:
			# Se recibe una bala
				try:
					angulo, x, y = int(valores[2]), int(valores[3]), int(valores[4])
					self.procesar_datos_balas(angulo=angulo, x=x, y=y)
				except:
					return
			
			elif "D" in valores:
			# self.procesar_datos_puntos(mensaje)
				# mensaje_puntos = "%s %s %s%s" % ("D", self.energia, self.puntaje, TERMINATOR)
				energia, puntaje = int(valores[1]), int(valores[2])
				self.procesar_datos_puntos(energia=energia, puntaje=puntaje)

			elif "P" in valores:
			# simple presencia en la red
				pass

			else:
				#print "Recibiendo Otras Cosas: ", mensaje, "***"
				pass

	# ---------------------inicio PERSISTENCIA DE DATOS -----------------------------------
	def procesar_datos_puntos(self, energia=100, puntaje=0):
	# hay cambios de puntaje o energía
		ESPEJO.Tanques[self.client_address[0]].set_puntos(energia=energia, puntaje=puntaje)
		ESPEJO.Tanques[self.client_address[0]].set_jugadores_por_informar_puntaje(ESPEJO.Tanques.keys())

	def procesar_datos_balas(self, angulo=0, x=0, y=0):
	# ha llegado una bala
		ESPEJO.Tanques[self.client_address[0]].set_bala(angulo=angulo, x=x, y=y) # crea la bala
		ESPEJO.Tanques[self.client_address[0]].set_jugadores_por_informar_disparo(ESPEJO.Tanques.keys())
		# pasa la lista de todos los jugadores para informar del disparo, a medida que se informa, se eliminan de la lista
		
	def procesar_datos_tanques(self, nombre=None, angulo=0, x=0, y=0):
	# Actualiza los datos del tanque de este jugador. Si el Jugador no existe, lo agrega.
		if nombre == None:
		# si no hay nombre no puede procesarse
			return

		if not self.client_address[0] in ESPEJO.Tanques.keys():
		# Si no existe, se agrega
			ESPEJO.Tanques[self.client_address[0]] = ESPEJO.Tanque(nombre)
			ESPEJO.Tanques[self.client_address[0]].set_datos_tanque(nombre=nombre, angulo=angulo, x=x, y=y)
		else:
		# Si existe se actualiza
			ESPEJO.Tanques[self.client_address[0]].set_datos_tanque(nombre=nombre, angulo=angulo, x=x, y=y)
	# ---------------------fin PERSISTENCIA DE DATOS -----------------------------------

	def enviar_datos(self):
	# A quien se conectó se le envían los datos de todos, también los suyos.

		mensaje = ""
		for jugador in ESPEJO.Tanques.values():				# para todos los jugadores.
			mensaje += jugador.get_datos_tanque()			# obtener las posiciones de tanques.
			
			bala = jugador.get_bala()
			if bala != None and self.client_address[0] in jugador.jugadores_por_informar_disparo:
			# Si hay una bala en juego de este jugador y el que se ha conectado no ha sido informado:
				mensaje += bala
				jugador.jugadores_por_informar_disparo.remove(self.client_address[0]) # borrar de la lista, ya se le informó
				if not jugador.jugadores_por_informar_disparo: jugador.bala = None

			if jugador.jugadores_por_informar_puntaje:
				if self.client_address[0] in jugador.jugadores_por_informar_puntaje:
				# Si hay cambios de puntaje y el que se ha conectado no ha sido informado:
					mensaje += jugador.get_puntos()
					jugador.jugadores_por_informar_puntaje.remove(self.client_address[0]) # borrar de la lista, ya se le informó

		if self.client_address[0] in ESPEJO.Tanques.keys():
		# evitar error de escaner de red de los clientes
			if ESPEJO.Tanques[self.client_address[0]].desconectados:
			# si hay información de desconexión de algún jugador
				mensaje += ESPEJO.Tanques[self.client_address[0]].desconectados
				ESPEJO.Tanques[self.client_address[0]].desconectados = ""

		if len(mensaje) > ESPEJO.CARGA:
			ESPEJO.CARGA = len(mensaje)
			print "Carga en la red: ", ESPEJO.CARGA
		self.request.send(mensaje)

	def setup(self):
	# Llamado antes de la handle() para realizar acciones de inicialización necesaria. La implementación predeterminada no hace nada.
		#print "Server Setup"
		#return SocketServer.BaseRequestHandler.setup(self)
		pass

	def finish(self):
	# Llamado despues de la handle() para realizar cualquier método de limpieza. La implementación predeterminada no hace nada.
		if self.client_address[0] in ESPEJO.Tanques.keys():
		# si está en la lista, porque da error cuando los clientes escanean la red en busca de servers, pero no están en el juego aun.
			print "Server Finish"
			for jugador in ESPEJO.Tanques.values():
			# para informar a todos los jugadores sobre la desconexión de otro jugador
				jugador.desconectados += "DES %s%s" % (ESPEJO.Tanques[self.client_address[0]].nombre, ESPEJO.TERMINATOR)
			del ESPEJO.Tanques[self.client_address[0]]
			#return SocketServer.BaseRequestHandler.finish(self)
		return



if __name__ == "__main__":
	server = ThreadedTCPServer(("localhost", 5000), ThreadedTCPRequestHandler)
	server.serve_forever()

	'''
	import SocketServer
	class MyHandler(SocketServer.BaseRequestHandler):
	   def handle(self):
	     while 1:
		dataReceived = self.request.recv(1024)
		self.request.send(dataReceived)
	myServer = SocketServer.ThreadingTCPServer(('',8881), MyHandler)
	myServer.serve_forever( )'''