Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > Blitz3D > 2D-программирование

2D-программирование Вопросы, касающиеся двумерного программирования

Ответ
 
Опции темы
Старый 02.10.2014, 21:41   #1
ILonion
ПроЭктировщик
 
Регистрация: 02.10.2014
Сообщений: 102
Написано 5 полезных сообщений
(для 25 пользователей)
TCP\IP клиент-сервер загвоздка

Доброго времени суток!
Разъясните незнающему, пожалуйста, кто в теме:

Сделал образцы сервера и клиента tcp. Работают...
Загвоздка в том, что если запустить 15+ клиентов, то сервер полностью зависает (на приеме пакетов. принт показывает приход 8192 байт с одного потока, в этот момент), пока не прибить некоторое кол-во клиентов.
В чем здесь причина? Неправильный размер пакета, переполнение TCP буфера...? Или еще что-то?
Разъясните кто-нибудь...

сервер:
;//////////////////////////////////////////////////////////////////////
;//////////////////////////////////////////////////////////////////////
;SERVER
;//////////////////////////////////////////////////////////////////////
;//////////////////////////////////////////////////////////////////////

;request code (action id):
	;SERVER > CLIENT
		;1001 - create player
		;1004 - update pos
		
	;CLIENT > SERVER
		;1002 - request
	
	;global vars:
	Global player_count
	Global PACK_SIZE = 536 ;bytes
	Global PORT = 49001

	Type player_type
		Field player_counter
		Field x#,y#,z#
		Field mesh
		Field stream
	End Type
	
	;global massives:
	Global S_server
	Global S_serv_bank = CreateBank(PACK_SIZE)

	
	;default mode for pivots:
	Graphics3D 320,240,0,2

	;CREATE SERVER:
	S_server = CreateTCPServer(PORT)
	If Not S_server
		RuntimeError "cannot create"
		End
	Else
		Print "created"
	End If





;###########################################################################################
	;loop
;###########################################################################################
While Not KeyHit(1)
	
	;CONNECT\CREATE NEW PLAYER:
	S_define_new_stream()

	;READ REQUESTS FROM CLIENT:
	For p.player_type = Each player_type
		If p.player_type <> Null
			If Not Eof(p\stream)
;debug:
If ReadAvail(p\stream) > 0
;DebugLog "incoming bytes: " + ReadAvail(p\stream)
Print "incoming bytes: " + ReadAvail(p\stream)
End If
;debug.
				Repeat
					If ReadAvail(p\stream) => PACK_SIZE
						ReadBytes(S_serv_bank,p\stream,0,PACK_SIZE)
						;request code:
						If PeekInt(S_serv_bank,0) = 1002
							;request type:
							inner_request = PeekInt(S_serv_bank,4)
							;execute request:
							S_request_execute(p.player_type,inner_request)
							
							;send result of request execute to all clients:
							x# = EntityX(p\mesh)
							y# = EntityY(p\mesh)
							z# = EntityZ(p\mesh)
							yaw# = EntityYaw#(p\mesh)
							p\x = x
							p\y = y
							p\z = z
							pl_id = p\player_counter
							ACTION_ID = 1004
							S_send_actions_to_all(ACTION_ID,x#,y#,z#,yaw#,pl_id)
							
						End If
					End If
				Until ReadAvail(p\stream) < PACK_SIZE
			Else
				Print "client crashed"
				Delete p
			End If
		End If
	Next
	
Wend
;###########################################################################################
Function S_define_new_stream()
;connect\create new player:

	;if new stream (client) defined: 
	S_inner_stream = AcceptTCPStream(S_server)
	If S_inner_stream
		
		Print "new player connected"
		
		;NEW PLAYER (local. create pivot like pos\rot clone (header) of client player entity):
			p.player_type = New player_type
			;player link (stream) = connected stream id:
			p\stream = S_inner_stream
			;player pivot:
			p\mesh = CreatePivot()
			;counter (id):
			player_count = player_count + 1
			Print "count of players: " + player_count
			
		;SEND TO ALL: CREATE NEW PLAYER:
			PositionEntity p\mesh,0,0,0
			p\player_counter = player_count
			pl_id = player_count
			x# = EntityX(p\mesh)
			y# = EntityY(p\mesh)
			z# = EntityZ(p\mesh)
			p\x = x
			p\y = y
			p\z = z
			ACTION_ID = 1001
			S_send_actions_to_all(ACTION_ID,x#,y#,z#,yaw#,pl_id)
			
		;SEND TO NEW STREAM: ALL EXIST PLAYERS:
			For p.player_type = Each player_type
				;if not eof:
				If Not Eof(S_inner_stream)
					;and not self:
					If p\player_counter <> player_count
						;action id:
						PokeInt S_serv_bank,0,1001
						;x,y,z
						PokeFloat S_serv_bank,4,p\x
						PokeFloat S_serv_bank,8,p\y
						PokeFloat S_serv_bank,12,p\z
						;id
						PokeInt S_serv_bank,16,p\player_counter
						;send
						WriteBytes S_serv_bank,S_inner_stream,0,PACK_SIZE
					End If
				Else
					Print "client crashed"
					Delete p
				End If
			Next
	End If
	
End Function
;###########################################################################################
Function S_request_execute(p.player_type,inner_request)
;execute request:

	speed# = 0.9

	;request type:
	Select inner_request
		;z+
		Case 1
			;move server pivot:
			MoveEntity p\mesh,0,0,speed
		;z-
		Case 2
			MoveEntity p\mesh,0,0,-speed
		;x+
		Case 3
			TurnEntity p\mesh,0,1,0
		;x-
		Case 4
			TurnEntity p\mesh,0,-1,0
		;y+
	;	Case 5
	;		TurnEntity p\mesh,0,1,0
		;y-
	;	Case 6
	;		TurnEntity p\mesh,0,-1,0
	End Select
	
End Function
;###########################################################################################
Function S_send_actions_to_all(ACTION_ID,x#,y#,z#,yaw#,pl_id)
;send actions to all clients:

	For p.player_type = Each player_type
		If p.player_type <> Null
			If Not Eof(p\stream)
				;action:
				PokeInt S_serv_bank,0,ACTION_ID
				;x,y,z
				PokeFloat S_serv_bank,4,x#
				PokeFloat S_serv_bank,8,y#
				PokeFloat S_serv_bank,12,z#
				PokeFloat S_serv_bank,20,yaw#
				;id
				PokeInt S_serv_bank,16,pl_id
				;send:
				WriteBytes S_serv_bank,p\stream,0,PACK_SIZE
			Else
				Print "client crashed"
				Delete p
			End If
		End If
	Next
	
End Function
клиент:
;//////////////////////////////////////////////////////////////////////
;//////////////////////////////////////////////////////////////////////
;CLIENT
;//////////////////////////////////////////////////////////////////////
;//////////////////////////////////////////////////////////////////////

;request code (action id):
	;SERVER > CLIENT
		;1001 - create player
		;1004 - update pos
		
	;CLIENT > SERVER
		;1002 - request
		
		
	;global vars:
	Global game_limit_speed = CreateTimer(60)
	;
	Global PACK_SIZE = 536 ;bytes
	Global PORT = 49001
	Global IP$ = "localhost" ;set ip here
	;
	Global player_created

	Type player_type
		Field player_counter
		Field x#,y#,z#
		Field mesh
	End Type
	
	;global massives:
	Global C_server_link
	Global C_client_bank = CreateBank(PACK_SIZE) 


	;graphics:
	Graphics3D 640,480,16,2
	
	;3d misc for scene:
	Global light = CreateLight(1)
	PositionEntity light,0,10,0
	Global player_mesh = CreateSphere()
	HideEntity player_mesh
	Global box = CreateCube()
	Global camera = CreateCamera()
	PositionEntity camera,0,20,-15
	RotateEntity camera,50,0,0
	CameraZoom camera,2
	CameraFogRange camera,2,100
	CameraFogMode camera,True
	CameraFogColor camera,150,200,255
	CameraClsColor camera,150,200,255
	grass=CreateTexture(64,64,1)
	SetBuffer TextureBuffer(grass)
	ClsColor 22,100,22
	Cls
	For i=0 To 256
		Color 0+Rnd(10),50+Rnd(155),0+Rnd(10)
		Plot Rnd(64),Rnd(64)
	Next
	SetBuffer BackBuffer()
	ScaleTexture grass,3,3  
	Color 255,255,255
	ClsColor 0,0,0
	plane=CreatePlane()
	EntityTexture plane,grass


	;CONNECT TO SERVER:
	;Print "PRESS ENTER"
	Repeat
		;If KeyHit(28);enter
			C_connect_to_server()
		;End If
	Until C_server_link <> 0




;###########################################################################################
	;loop
;###########################################################################################
period = 1000 / 40
time = MilliSecs() - period

While Not KeyHit(1)

	;waiter:
	WaitTimer(game_limit_speed)
	
	;fractional remainder:
	Repeat
		elapsed = MilliSecs() - time
	Until elapsed
	ticks=elapsed/period
	tween#=Float(elapsed Mod period)/Float(period)
	For k=1 To ticks
		If k=ticks Then CaptureWorld
		time=time+period
			;##########################
				;
				calculate_game()
				;
			;##########################
		UpdateWorld
	Next
	AntiAlias True
	RenderWorld tween
	
	;wire:
	If KeyHit(57)
		wire = 1 - wire
	End If
	WireFrame wire
	
	;pl.count:
	i = 0
	For p.player_type = Each player_type
		i = i + 1
	Next
	Text 10,40,i + " - players"
	
	Flip
Wend
;###########################################################################################
Function calculate_game()

	;READ REQUESTS FROM SERVER:
	If Not Eof(C_server_link)
		Repeat
			If ReadAvail(C_server_link) => PACK_SIZE
				ReadBytes(C_client_bank,C_server_link,0,PACK_SIZE)
				;INITIALIZE ME:
				If player_created = 0
					;create me:
					If PeekInt(C_client_bank,0) = 1001
						;create me:
						p.player_type = New player_type
						p\mesh = CopyEntity(player_mesh)
						anim_entity = p\mesh
						ShowEntity p\mesh
						p\player_counter = PeekInt(C_client_bank,16)
						x# = PeekFloat(C_client_bank,4)
						y# = PeekFloat(C_client_bank,8)
						z# = PeekFloat(C_client_bank,12)
						PositionEntity p\mesh,x,y,z
						;
						;player created (me):
						player_created = 1
					End If
					
				;ALL OTHER ACTIONS:
				End If
				If player_created = 1
					;create other players:
					If PeekInt(C_client_bank,0) = 1001
						p.player_type = New player_type
						p\mesh = CopyEntity(player_mesh)
						ShowEntity p\mesh
						p\player_counter = PeekInt(C_client_bank,16)
						x# = PeekFloat(C_client_bank,4)
						y# = PeekFloat(C_client_bank,8)
						z# = PeekFloat(C_client_bank,12)
						PositionEntity p\mesh,x,y,z
					End If
					
					;update pos (me and other):
					If PeekInt(C_client_bank,0) = 1004
						id = PeekInt(C_client_bank,16)
						For p.player_type = Each player_type
							If p\player_counter = id
								x# = PeekFloat(C_client_bank,4)
								y# = PeekFloat(C_client_bank,8)
								z# = PeekFloat(C_client_bank,12)
								yaw# = PeekFloat(C_client_bank,20)
								PositionEntity p\mesh,x,y,z
								RotateEntity p\mesh,0,yaw,0
							End If
						Next
					End If
				End If
			End If
		Until ReadAvail(C_server_link) < PACK_SIZE
	Else
		RuntimeError "server crashed"
		End 
	End If
	
	;SEND REQUESTS TO SERVER:
	If player_created = 1
		;random player motion:
		SeedRnd MilliSecs()
		request = Rand(1,4)
		C_server_request(request)
			
		;manual motion:
	;	If KeyDown(200);z+
	;		request = 1
	;		C_server_request(request)
	;	End If
	;	If KeyDown(208);z-
	;		request = 2
	;		C_server_request(request)
	;	End If
	;	If KeyDown(205);x+
	;		request = 3
	;		C_server_request(request)
	;	End If
	;	If KeyDown(203);x-
	;		request = 4
	;		C_server_request(request)
	;	End If
	End If

End Function
;###########################################################################################
Function C_connect_to_server()
;connect to server:

	Print "connecting..."
	C_server_link = OpenTCPStream(IP$,PORT)
	If Not C_server_link
		RuntimeError "failed"
		End
	End If

End Function
;###########################################################################################
Function C_server_request(request)
;send request:

	If Not Eof(C_server_link)
		PokeInt C_client_bank,0,1002
		PokeInt C_client_bank,4,request
		WriteBytes C_client_bank,C_server_link,0,PACK_SIZE
	Else
		RuntimeError "server crashed"
	End If
	
End Function
(Offline)
 
Ответить с цитированием
Старый 02.10.2014, 23:37   #2
moka
.
 
Регистрация: 05.08.2006
Сообщений: 10,429
Написано 3,454 полезных сообщений
(для 6,863 пользователей)
Ответ: TCP\IP клиент-сервер загвоздка

Я писал сетевые приложения на блице, были проблемы с 10+ клиентами тоже. Разные, и все очень странные.
В основном дело в том что с сетью в блокирующем контексте работать по опреелению - нельзя. Причин много, и об этом не мало литературы.
Следственно серверные решения нужно писать в асинхронной либо мультипоточной модели.
Первая - асинхронная, показала себя как весьма масштабируемая и применяется в очень большом спектре реальных серверных решений.
Но блиц не поддерживает никакой асинхронности в коде. Я не знаю как там задник сделан, но проблемы я свои еще много лет назад по поводу сети на нем так и не решил.

Рассмотри другие языки для серверной логики.
Также серверная логика не имеет ничего общего к клиентской, та же система Entity и всякие рендеры, коллизия и т.п. - все очень отличается на серверах от клиентов.
Следственно тут не суть важно какое серверное решение ты выберешь, если оно не походит на клинета - это не аргумент вообще.

Если знаешь JS, пиши на node.js - так будет проще стартовать, и быстрее будет результат.
(Offline)
 
Ответить с цитированием
Эти 4 пользователя(ей) сказали Спасибо moka за это полезное сообщение:
ILonion (03.10.2014), impersonalis (03.10.2014), L-ee-X (05.10.2014), St_AnGer (03.10.2014)
Старый 03.10.2014, 00:24   #3
impersonalis
Зануда с интернетом
 
Аватар для impersonalis
 
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений
(для 20,935 пользователей)
Ответ: TCP\IP клиент-сервер загвоздка

Можно попробовать размазать опрос по времени, внеся правку: читать полученные сообщение не "пока не прочитан PACK целиком", а "N байт и выходить из обработки". Но такая асинхронность выйдет боком: код запутается и станет скорее изыском, лучше, конечно, запилить асинхронность на потоках. Например (при неимении возможности поступить как советует moka), написать dll на чём-то многопоточность поддерживающем, и либо общаться через блокирующие blitz-прогу функции (ЕстьЛиГотовыйПак(), ПролучитьЗагурженныйПак()), либо через общий буфер (число, возвращаемое CreateBank - реальный адрес памяти, который можно использовать в DLL), имеющий маркер (изменяемый атомарно) для управления синхронизацией ("пакет готов","ожидаю следующий пакет") и область под тело пакета.
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
ILonion (03.10.2014)
Старый 03.10.2014, 01:21   #4
ILonion
ПроЭктировщик
 
Регистрация: 02.10.2014
Сообщений: 102
Написано 5 полезных сообщений
(для 25 пользователей)
Ответ: TCP\IP клиент-сервер загвоздка

moka, impersonalis, благодарю вас!
Теперь имею представление о происходящем.
Буду думать над предложениями...
(Offline)
 
Ответить с цитированием
Старый 04.10.2014, 16:14   #5
L-ee-X
Разработчик
 
Аватар для L-ee-X
 
Регистрация: 06.06.2011
Адрес: Ирк. обл.
Сообщений: 541
Написано 133 полезных сообщений
(для 220 пользователей)
Ответ: TCP\IP клиент-сервер загвоздка

Проще серверную часть на другом яп. писать . Пиши в лс могу помочь. Даже кодом поделюсь реализации серверной части.
__________________
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
ILonion (04.10.2014)
Старый 04.10.2014, 20:20   #6
ILonion
ПроЭктировщик
 
Регистрация: 02.10.2014
Сообщений: 102
Написано 5 полезных сообщений
(для 25 пользователей)
Ответ: TCP\IP клиент-сервер загвоздка

L-ee-X, большущее спасибо!
Решил пока что оставить сетевые вопросы, и взяться за другое.

P.S. Если кому-то будет интересно:
В вышеприведенном примере удалось сделать нормальную работу с 54 клиентами (еще больше клиентов "матрица" видеокарты не позволяла шибко, а без граф. режима дописывать и проверять просто не стал), через реализацию ожидания ответа от сервера (ничего не предпринимать) на конкретный запрос клиента.
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 09:28.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com