Página 1 de 1

Duda con TcpAccept

Publicado: 11 Abr 2010, 20:24
por Fredinchy
Hola a todos espero que estén bien! :smt001
Bueno abro este tema porque estoy en un proyecto de chat pero no consigo aceptar diversas conexiones.. solo acepto una conexión con un server como el que esta en la ayuda.

Me he puesto a buscar y veo que en el foro en inglés John2010zz ha logrado hacerlo. El detalle es que viendo el código sigo sin entenderlo.
Aquí esta el server

Código: Seleccionar todo

#Include <ButtonConstants.Au3>
#Include <EditConstants.Au3>
#Include <GUIConstantsEx.Au3>
#Include <StaticConstants.Au3>
#Include <WindowsConstants.Au3>
#Include <File.Au3>
#Include <String.Au3>
#NoTrayIcon

Opt ('GUIOnEventMode', 1)

Global $Max = 10, $Socket[$Max + 1], $User[$Max + 1], $Server = -1, $Admin = -1, $Admin_Pw = 'password', $Connected = 0
For $A = 1 To $Max
	$Socket[$A] = -1
	$User[$A] = -1
Next

$GUI = GUICreate ('Server Settings', 180, 100, -1, -1, -1, 128)
GUISetOnEvent  ($GUI_EVENT_CLOSE, '_Exit')
GUICtrlCreateGroup  ('', 5, 0, 170, 94)
$IP = GUICtrlCreateInput (@IpAddress1, 12, 13, 100, 21, 1)
$Port = GUICtrlCreateInput (50, 117, 13, 50, 21, 1)
$Start = GUICtrlCreateButton ('Start', 12, 39, 46, 20, $WS_GROUP)
GUICtrlSetOnEvent ($Start, '_Start')
$Stop = GUICtrlCreateButton ('Stop', 63, 39, 49, 20, $WS_GROUP)
GUICtrlSetState ($Stop, $GUI_DISABLE)
GUICtrlSetOnEvent ($Stop, '_Stop')
$Pw = GUICtrlCreateInput ($Admin_Pw, 12, 65, 100, 21, BitOr (1, $ES_PASSWORD))
$Set = GUICtrlCreateButton ('Set Pw', 118, 66, 49, 20, $WS_GROUP)
GUICtrlSetOnEvent ($Set, '_Set')
GUISetState (@SW_SHOW)
WinSetOnTop ($GUI, '', 1)

While 1
	If $Server <> -1 Then
		If $Connected < $Max Then
			$Accept = TcpAccept ($Server)
			If $Accept <> -1 Then
				If _IsBanned (_SocketGetIP ($Accept)) = 0 Then
					$Open = _Open ()
					$Timer = TimerInit ()
					Do
						Sleep (15)
						$Recv = TcpRecv ($Accept, 1000000)
					Until $Recv <> '' Or TimerDiff ($Timer) >= 500
					If $Recv <> '' Then
						If _Check ($Recv) = 1 Then
							$User[$Open] = $Recv
							$Socket[$Open] = $Accept
							$Connected = $Connected + 1
							_SendAll ('[%Time] ' & $User[$Open] & ' has connected.')
						Else
							TcpSend ($Accept, 'Error:Username.Exists;')
							Sleep (250)
							TcpCloseSocket ($Accept)
						EndIf
					Else
						TcpCloseSocket ($Accept)
					EndIf
				Else
					TcpSend ($Accept, 'Error:IP.Banned;')
					Sleep (250)
					TcpCloseSocket ($Accept)
				EndIf
			EndIf
		ElseIf $Connected = $Max Then
			$Accept = TcpAccept ($Server)
			If $Accept <> -1 Then
				$Timer = TimerInit ()
				Do
					Sleep (15)
					$Recv = TcpRecv ($Accept, 1000000)
				Until $Recv <> '' Or TimerDiff ($Timer) >= 500
				Sleep (250)
				TcpSend ($Accept, 'Error:Max.Connections;')
				TcpCloseSocket ($Accept)
			EndIf
		EndIf
		For $A = 1 To $Max
			If $Socket[$A] <> -1 And $User[$A] <> -1 Then
				$Recv = TcpRecv ($Socket[$A], 1000000)
				If @Error Then _Disconnect ($A)
				If $Recv <> '' Then
					If StringLeft ($Recv, 6) = '.admin' Then
						If $Admin <> -1 Then
							TcpSend ($Socket[$A], '[%Time] Server : An admin is already logged in.')
						Else
							If StringTrimLeft ($Recv, 7) == $Admin_Pw Then
								$Admin = $User[$A]
								_SendAll ('[%Time] ' & $User[$A] & ' is now an admin.')
							Else
								TcpSend ($Socket[$A], '[%Time] Server : Incorrect admin password.')
							EndIf
						EndIf
					ElseIf StringLeft ($Recv, 7) = '.logout' Then
						If $User[$A] == $Admin Then
							$Admin = -1
							_SendAll ('[%Time] ' & $User[$A] & ' is no longer an admin.')
						Else
							TcpSend ($Socket[$A], '[%Time] Server : You do not have this power.')
						EndIf
					ElseIf StringLeft ($Recv, 5) = '.kick' Then
						If $User[$A] == $Admin Then
							$Who = StringTrimLeft ($Recv, 6)
							If $Who = $Admin Then
								TcpSend ($Socket[$A], '[%Time] Server : You cannot kick an admin.')
							ElseIf _UserGetSocket ($Who) <> -1 Then
								_Disconnect (_UserGetSocket ($Who))
							Else
								TcpSend ($Socket[$A], '[%Time] Server : User does not exist.')
							EndIf
						Else
							TcpSend ($Socket[$A], '[%Time] Server : You do not have this power.')
						EndIf
					ElseIf StringLeft ($Recv, 6) = '.stats' Then
						$Stats = @CRLF & 'Total Online : ' & $Connected & @CRLF
						For $B = 1 To $Max
							If $Socket[$B] <> -1 And $User[$B] <> -1 Then
								$Stats = $Stats & '[' & $B& '] ' & $User[$B] & @CRLF
							EndIf
						Next
						TcpSend ($Socket[$A], $Stats)
					ElseIf StringLeft ($Recv, 3) = '.ip' Then
						If $User[$A] == $Admin Then
							$Who = StringTrimLeft ($Recv, 4)
							$wID = _UserGetSocket ($Who)
							If $wID <> -1 Then
								TcpSend ($Socket[$A], '[%Time] Server : ' & $Who & "'s IP : " & _SocketGetIP ($Socket[$wID]))
							Else
								TcpSend ($Socket[$A], '[%Time] Server : User does not exist.')
							EndIf
						Else
							TcpSend ($Socket[$A], '[%Time] Server : You do not have this power.')
						EndIf
					ElseIf StringLeft ($Recv, 4) = '.ban' Then
						If $User[$A] == $Admin Then
							$Who = StringTrimLeft ($Recv, 5)
							$wID = _UserGetSocket ($Who)
							If $Who = $Admin Then
								TcpSend ($Socket[$A], '[%Time] Server : You cannot ban an admin.')
							ElseIf $wID <> -1 Then
								$IP = _SocketGetIP ($Socket[$wID])
								FileWriteLine ('Banned.txt', $IP)
								For $B = 1 To $Max
									If $Socket[$B] <> -1 And $User[$B] <> -1 Then
										If _SocketGetIP ($Socket[$B]) = $IP Then _Disconnect ($B)
									EndIf
								Next
								_SendAll ('[%Time] IP : ' & $IP & ' has been banned.')
								Sleep (500)
								TcpSend ($Socket[$A], '.log Ban Added : Username : ' & $Who & ', IP : ' & $IP)
							Else
								TcpSend ($Socket[$A], '[%Time] Server : User does not exist.')
							EndIf
						Else
							TcpSend ($Socket[$A], '[%Time] Server : You do not have this power.')
						EndIf
					ElseIf StringLeft ($Recv, 6) = '.unban' Then
						If $User[$A] == $Admin Then
							$IP = StringTrimLeft ($Recv, 7)
							If _IsBanned ($IP) = 1 Then
								_Remove ($IP)
								_SendAll ('[%Time] IP ' & $IP & ' is un-banned.')
								Sleep (500)
								TcpSend ($Socket[$A], '.log Ban Removed : ' & $IP)
							Else
								TcpSend ($Socket[$A], '[%Time] Server : ' & $IP & ' is not banned.')
							EndIf
						Else
							TcpSend ($Socket[$A], '[%Time] Server : You do not have this power.')
						EndIf
					Else
						_SendAll ('[%Time] ' & $User[$A] & ' says : ' & $Recv)
					EndIf
				EndIf
			EndIf
		Next
	EndIf
	Sleep (15)
WEnd

Func _IsBanned ($Data)
	For $A = 1 To _FileCountLines ('Banned.txt')
		If FileReadLine ('Banned.txt', $A) = $Data Then Return 1
	Next
	Return 0
EndFunc

Func _Remove ($IP)
	$Count = _FileCountLines ('Banned.txt')
	If $Count = 1 And FileReadLine ('Banned.txt', 1) = $IP Then
		FileDelete ('Banned.txt')
	ElseIf $Count > 0 Then
		For $A = 1 To $Count
			$Line = FileReadLine ('Banned.txt', $A)
			If $Line <> $IP Then FileWriteLine ('Banned_Temp.txt', $Line)
		Next
	EndIf
	FileCopy ('Banned_Temp.txt','Banned.txt', 1)
	FileDelete ('Banned_Temp.txt')
EndFunc

Func _SocketGetIP ($Data)
	Local $Struct, $Return
	$Struct = DllStructCreate ('short;ushort;uint;char[8]')
    $Return = DllCall ('Ws2_32.dll','int','getpeername','int', $Data, 'ptr', DllStructGetPtr ($Struct), 'int*', DllStructGetSize($Struct))
	If @Error Or $Return[0] <> 0 Then Return 0
	$Return = DllCall ('Ws2_32.dll','str','inet_ntoa','int', DllStructGetData ($Struct, 3))
	If @Error Then Return 0
	$Struct = 0
	Return $Return[0]
EndFunc

Func _UserGetSocket ($Data)
	For $A = 1 To $Max
		If $User[$A] = $Data Then Return $A
	Next
	Return -1
EndFunc

Func _Check ($Data)
	For $A = 1 To $Max
		If $User[$A] = $Data Then Return 0
	Next
	Return 1
EndFunc

Func _Disconnect ($ID)
	_SendAll ('[%Time] ' & $User[$ID] & ' has disconnected.')
	If $User[$ID] = $Admin Then $Admin = -1
	TcpCloseSocket ($Socket[$ID])
	$Socket[$ID] = -1
	$User[$ID] = -1
	$Connected = $Connected - 1
EndFunc

Func _SendAll ($Msg)
	For $A = 1 To $Max
		If $Socket[$A] <> -1 And $User[$A] <> -1 Then
			TcpSend ($Socket[$A], $Msg)
		EndIf
	Next
EndFunc

Func _Open ()
	For $A = 1 To $Max
		If $Socket[$A] = -1 And $User[$A] = -1 Then Return $A
	Next
EndFunc

Func _Start ()
	If GUICtrlRead ($IP) == '' Or GUICtrlRead ($Port) == '' Then Return @Error
	TcpStartUp ()
	$Server = TcpListen (GUICtrlRead ($IP), GUICtrlRead ($Port))
	If $Server = -1 Or @Error Then
		WinSetOnTop ($GUI, '', 0)
		Sleep (100)
		MsgBox (16, 'Fatal Error','Unable to start the server, change your settings and try again.')
		WinSetOnTop ($GUI, '', 1)
		TcpCloseSocket ($Server)
		_Reset ()
	Else
		GUICtrlSetState ($IP, $GUI_DISABLE)
		GUICtrlSetState ($Port, $GUI_DISABLE)
		GUICtrlSetState ($Start, $GUI_DISABLE)
		GUICtrlSetState ($Stop, $GUI_ENABLE)
	EndIf
EndFunc

Func _Stop ()
	TcpCloseSocket ($Server)
	$Server = -1
	$Connected = 0
	$Admin = -1
	_Reset ()
EndFunc

Func _Set ()
	$Admin_Pw = GUICtrlRead ($Pw)
EndFunc

Func _Reset ()
	For $A = 1 To $Max
		If $Socket[$A] <> -1 Or $User[$A] <> -1 Then
			TcpCloseSocket ($Socket[$A])
			$Socket[$A] = -1
			$User[$A] = -1
		EndIf
	Next
	TcpShutDown ()
	GUICtrlSetState ($IP, $GUI_ENABLE)
	GUICtrlSetState ($Port, $GUI_ENABLE)
	GUICtrlSetState ($Start, $GUI_ENABLE)
	GUICtrlSetState ($Stop, $GUI_DISABLE)
EndFunc

Func _Exit ()
	Exit
EndFunc
Yo veo el TcpAccept($Server) pero en que momento el $Server cambia el valor del -1? de verdad no lo entiendo. :smt017

Aquí el cliente:

Código: Seleccionar todo

#Include <ButtonConstants.Au3>
#Include <EditConstants.Au3>
#Include <GUIConstantsEx.Au3>
#Include <StaticConstants.Au3>
#Include <WindowsConstants.Au3>
#Include <GUIEdit.Au3>
#Include <Misc.Au3>
#NoTrayIcon

Opt ('GUIOnEventMode', 1)
TcpStartUp ()

Global $Server = -1, $Logs

$Settings = GUICreate ('Connection Settings', 180, 100, -1, -1, -1, 128)
GUISetOnEvent  ($GUI_EVENT_CLOSE, '_Exit')
GUICtrlCreateGroup  ('', 5, 0, 170, 94)
$IP = GUICtrlCreateInput (IniRead ('Settings.ini','Settings','IP', @IpAddress1), 12, 13, 100, 21, 1)
$Port = GUICtrlCreateInput (IniRead ('Settings.ini','Settings','Port', 50), 117, 13, 50, 21, 1)
$User = GUICtrlCreateInput (IniRead ('Settings.ini','Settings','User','John'), 12, 39, 156, 21, 1)
$Connect = GUICtrlCreateButton ('Connect', 12, 66, 100, 20, $WS_GROUP)
GUICtrlSetOnEvent ($Connect, '_Start')
$Exit = GUICtrlCreateButton ('Exit', 117, 66, 50, 20, $WS_GROUP)
GUICtrlSetOnEvent ($Exit, '_Exit')
GUISetState (@SW_SHOW)
WinSetOnTop ($Settings, '', 1)

$GUI = GUICreate ('TCP Chat Room', 375, 275, -1, -1, -1, 128)
GUISetOnEvent ($GUI_EVENT_CLOSE, '_Toggle')
$History = GUICtrlCreateEdit ('', 0, 1, 375, 203, 2103360 + $ES_MULTILINE)
GUICtrlSetFont ($History, 10, -1, -1, 'Lucida Sans Unicode')
GUICtrlSetBkColor ($History, 0x83B4FC)
GUICtrlSetColor ($History, 0xFFFFFF)
$Send = GUICtrlCreateEdit ('', 0, 205, 375, 70, 2101248)
GUICtrlSetFont ($Send, 10, -1, -1, 'Lucida Sans Unicode')
GUICtrlSetColor ($Send, 0x83B4FC)
GUISetState (@SW_HIDE)

While 1
	Sleep (15)
	If $Server <> -1 Then
		$Recv = TcpRecv ($Server, 1000000)
		If @Error Then
			GUISetState (@SW_HIDE, $GUI)
			WinSetOnTop ($GUI, '', 0)
			Sleep (100)
			MsgBox (48, 'Server Notice','You have been disconnected from the server.')
			_Disconnect ()
		EndIf
		If $Recv = 'Error:Username.Exists;' Then
			GUISetState (@SW_HIDE, $GUI)
			WinSetOnTop ($GUI, '', 0)
			Sleep (100)
			MsgBox (48, 'Server Notice','Your username is already in use, please change it and try again.')
			_Disconnect ()
		ElseIf $Recv = 'Error:Max.Connections;' Then
			GUISetState (@SW_HIDE, $GUI)
			WinSetOnTop ($GUI, '', 0)
			Sleep (100)
			MsgBox (48, 'Server Notice','Max amount of connections reached, try again later.')
			_Disconnect ()
		ElseIf $Recv = 'Error:IP.Banned;' Then
			GUISetState (@SW_HIDE, $GUI)
			WinSetOnTop ($GUI, '', 0)
			Sleep (100)
			MsgBox (48, 'Server Notice','Your IP address has been banned.')
			_Disconnect ()
		ElseIf StringLeft ($Recv, 4) = '.log' Then
			FileWriteLine ('Logged.txt', StringTrimLeft ($Recv, 5))
		ElseIf $Recv <> '' Then
			_Log (StringReplace ($Recv, '%Time', @HOUR & ':' & @MIN))
		EndIf
		If _IsPressed ('0D') And GUICtrlRead ($Send) <> '' And ControlGetFocus ($GUI) = 'Edit2' Then
			$Read = StringReplace (GUICtrlRead ($Send), @CRLF, '')
			$Read = StringReplace ($Read, @CR, '')
			$Read = StringReplace ($Read, @LF, '')
			If $Read = '.clear' Then
				GUICtrlSetData ($History, '')
			ElseIf $Read = '.logs' Then
				_Logs ()
			ElseIf $Read = '.save' Then
				FileWrite (@MDAY & '-' & @MON & '-' & @YEAR & '_' & @HOUR & '-' & @MIN & '-' & @SEC & '_Logs.txt', GUICtrlRead ($History))
			ElseIf $Read = '.disconnect' Or $Read = '.exit' Then
				_Disconnect ()
			Else
				TcpSend ($Server, $Read)
			EndIf
			GUICtrlSetData ($Send, '')
		EndIf
	EndIf
WEnd

Func _Logs ()
	$Logs = GUICreate ('Admin Logs', 375, 203, -1, -1, -1, 128)
	GUISetOnEvent ($GUI_EVENT_CLOSE, '_Delete')
	$Edit = GUICtrlCreateEdit ('', 0, 1, 375, 203, 2103360 + $ES_MULTILINE)
	GUICtrlSetFont ($Edit, 10, -1, -1, 'Lucida Sans Unicode')
	GUICtrlSetBkColor ($Edit, 0x83B4FC)
	GUICtrlSetColor ($Edit, 0xFFFFFF)
	GUISetState (@SW_SHOW)
	GUICtrlSetData ($Edit, FileRead ('Logged.txt'))
	WinSetOnTop ($Logs, '', 1)
EndFunc

Func _Delete ()
	GUIDelete ($Logs)
EndFunc

Func _Disconnect ()
	GUICtrlSetData ($History, '')
	TcpCloseSocket ($Server)
	$Server = -1
	GUISetState (@SW_HIDE, $GUI)
	WinSetOnTop ($GUI, '', 0)
	GUISetState (@SW_SHOW, $Settings)
	WinSetOnTop ($Settings, '', 1)
EndFunc

Func _Toggle ()
	GUICtrlSetData ($History, '')
	TcpCloseSocket ($Server)
	$Server = -1
	GUISetState (@SW_HIDE, $GUI)
	WinSetOnTop ($GUI, '', 0)
	GUISetState (@SW_SHOW, $Settings)
	WinSetOnTop ($Settings, '', 1)
EndFunc

Func _Log ($Data)
	GUICtrlSetData ($History, GUICtrlRead ($History) & $Data & @CRLF)
	_GUICtrlEdit_LineScroll ($History, 0, _GUICtrlEdit_GetLineCount ($History) - 1)
EndFunc

Func _Start ()
	If GUICtrlRead ($User) == '' Or GUICtrlRead ($IP) == '' Or GUICtrlRead ($Port) == '' Then Return @Error
	$Server = TcpConnect (GUICtrlRead ($IP), GUICtrlRead ($Port))
	If $Server = -1 Or @Error Then
		WinSetOnTop ($Settings, '', 0)
		Sleep (100)
		MsgBox (16, 'Fatal Error','Unable to connect to the server, change your settings and try again.')
		WinSetOnTop ($Settings, '', 1)
		Return @Error
	EndIf
	Sleep (150)
	TcpSend ($Server, GUICtrlRead ($User))
	GUISetState (@SW_HIDE, $Settings)
	WinSetOnTop ($Settings, '', 0)
	GUISetState (@SW_SHOW, $GUI)
	WinSetOnTop ($GUI, '', 1)
EndFunc

Func _Exit ()
	IniWrite ('Settings.ini','Settings','IP', GUICtrlRead ($IP))
	IniWrite ('Settings.ini','Settings','Port', GUICtrlRead ($Port))
	IniWrite ('Settings.ini','Settings','User', GUICtrlRead ($User))
	Exit
EndFunc
Espero que me puedan explicar el TcpAccept

Saludos! :smt020

Re: Duda con TcpAccept

Publicado: 11 Abr 2010, 20:59
por BasicOs
Aquí puedes ver un ejemplo de la ayuda..
ves que el while va dando vueltas todo el rato hasta que cambia el valor de TcpAccept(), que muestra un msgbox.
Lo que hace el while es estar horas o minutos a la espera en un PUERTO del pc, hasta que otra conexión llegue.

Es como abrir la puerta un despacho y estar esperando que alguien entre. Desde que alguien entra se le da una chapita identificativa que es la IP+número de puerto ocupado para realizar transacciones de información, (envios y recepciones de bits o de palabras).

Código: Seleccionar todo

;SERVER!! Start Me First !!!!!!!!!!!!!!!
$g_IP = "127.0.0.1"

; Start The TCP Services
;==============================================
TCPStartUp()

; Create a Listening "SOCKET"
;==============================================
$MainSocket = TCPListen($g_IP, 65432,  100 )
If $MainSocket = -1 Then Exit

;  look for client connection
;--------------------
While 1
$ConnectedSocket = TCPAccept( $MainSocket)
If $ConnectedSocket >= 0 Then
    msgbox(0,"","my server - Client Connected")
    exit
EndIf
Wend
Cuando una petición de entrar a TcpAccept() tiene éxito, produce este "socket" que se usa por la función TCPRev() para ir recibiendo información.
Es decir normalmente el TCPAccept() exitoso, implica que la función $recv = TCPRecv($ConnectedSocket, 2048) va llenar de datos una variable ($recv) que se van recibiendo del pc Remoto.
Aqui tienes un trozo de la Ayuda.chm con el asunto:

Código: Seleccionar todo

;==============================================
    Do
        $ConnectedSocket = TCPAccept($MainSocket)
    Until $ConnectedSocket <> -1


    ; Get IP of client connecting
    $szIP_Accepted = SocketToIP($ConnectedSocket)

    ; GUI Message Loop
    ;==============================================
    While 1
        $msg = GUIGetMsg()

        ; GUI Closed
        ;--------------------
        If $msg = $GUI_EVENT_CLOSE Then ExitLoop

        ; Try to receive (up to) 2048 bytes
        ;----------------------------------------------------------------
        $recv = TCPRecv($ConnectedSocket, 2048)
Salu22:)

Re: Duda con TcpAccept

Publicado: 11 Abr 2010, 23:26
por Fredinchy
Muchas gracias por la respuesta.. No podía lograr múltiples conexiones hasta que me diste el ejemplo del despacho! :smt005

Saludos! :smt020

Re: Duda con TcpAccept

Publicado: 12 Abr 2010, 08:59
por Ximorro
¡Muy bueno lo del despacho! :smt044