msizec Posted September 15, 2010 Share Posted September 15, 2010 I still have the same problem.Once the 'Connected' event triggered a first time, and if the client disconnects for a reason, any other call of the Connect function will not trigger the 'Connected' event again.I made more tests and now I can tell that the 'Connected' event is triggered some times, and nopt triggerd some other times.It even happens at the first connection.For my tests, the server and the client are on the same pc.When a client has connected to the server, the server send a little command. I thought maybe the server was sending it to fast for the client to register his 3 events, but the problem is still here even with a sleep in the server's code.However there is no problem with the "reveived" and "connected" events. They're always triggered.Can you help me a bit kip plz ?Thx Link to comment Share on other sites More sharing options...
Kip Posted September 15, 2010 Author Share Posted September 15, 2010 Can you help me a bit kip plz ?ThxI'm afraid not. I don't know where the problem lies. MailSpons: Fake SMTP server for safe email testing Dutch postcode & address API. Link to comment Share on other sites More sharing options...
msizec Posted September 16, 2010 Share Posted September 16, 2010 I'm afraid not. I don't know where the problem lies.Do you think is about my code ?About the fact the server and the client are on the same host ?or maybe your UDF ? Link to comment Share on other sites More sharing options...
twitchyliquid64 Posted September 17, 2010 Share Posted September 17, 2010 Hi kip. I am re-writing your UDF to be able to act as both client and server (but not one or the other). As well as that, I will create a number of other functionalities that are useful for P2P software. On the agenda: _P2P_Start_Node( node identifier, Port, IP address, Lan or internet, Max peers, Auto connect to others max, etc) The node identifier is a number assigned to each individual user/computer that can uniquely identify them. Used as an address for long distance messages on large P2P networks. _P2P_Register_event( ) (Connect, Recv, Send, Newconn, closeconn, New message, AUX data) _P2P_Send( ) _P2P_Send_Message( node identifier, Data) And most of the others in your UDF. This is the message system I talked about. It works be routing the message to the relevant peers, who will route it to more peers, etc till it reaches destination. The UDF will manage message routing automatically. I have so far written rewritten your code so so far it: starts node, listens on port, accepts connections, passes all data (inc recv) onto scripts, able to connect to new peers, new Socket array. Most of the connection engine will be the same except that the correct array subscript will be mathamatically derived from the GUI register msg Info, rather than scanning the entire socket array, which slows down msg delievery when dealing with large amounts of connections. Additionally, message sends are automatically split; if I send three messages with no delay the TCP recv funcs merge them into one. My Version fixs this problem and keeps them separate. I hope you don't mind my re-write. I will give credit to your original design construct. Hypoz. ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search Link to comment Share on other sites More sharing options...
twitchyliquid64 Posted September 17, 2010 Share Posted September 17, 2010 Hi kip.I am re-writing your UDF to be able to act as both client and server (but not one or the other). As well as that, I will create a number of other functionalities that are useful for P2P software.On the agenda:_P2P_Start_Node( node identifier, Port, IP address, Lan or internet, Max peers, Auto connect to others max, etc)The node identifier is a number assigned to each individual user/computer that can uniquely identify them. Used as an address for long distance messages on large P2P networks._P2P_Register_event( ) (Connect, Recv, Send, Newconn, closeconn, New message, AUX data)_P2P_Send( )_P2P_Send_Message( node identifier, Data)And most of the others in your UDF.This is the message system I talked about. It works be routing the message to the relevant peers, who will route it to more peers, etc till it reaches destination. The UDF will manage message routing automatically. I have so far written rewritten your code so so far it: starts node, listens on port, accepts connections, passes all data (inc recv) onto scripts, able to connect to new peers, new Socket array. I hope to release the UDF in about a wk or so.Most of the connection engine will be the same except that the correct array subscript will be mathamatically derived from the GUI register msg Info, rather than scanning the entire socket array, which slows down msg delievery when dealing with large amounts of connections.Additionally, message sends are automatically split; if I send three messages with no delay the TCP recv funcs merge them into one. My Version fixs this problem and keeps them separate.I hope you don't mind my re-write. I will give credit to your original design construct.Hypoz. ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search Link to comment Share on other sites More sharing options...
Kip Posted September 17, 2010 Author Share Posted September 17, 2010 (edited) What the hell is that quote supposed to do?if I send three messages with no delay the TCP recv funcs merge them into one. My Version fixs this problem and keeps them separate.That's not a problem: That's how TCP works. Edited September 17, 2010 by Kip MailSpons: Fake SMTP server for safe email testing Dutch postcode & address API. Link to comment Share on other sites More sharing options...
twitchyliquid64 Posted September 20, 2010 Share Posted September 20, 2010 What the hell is that quote supposed to do?That's not a problem: That's how TCP works.Ok. What I meant to say was;basically, as you said, TCP appends messages sent in quick succession together.This is an issue for code that looks for specific strings as the string can sometimes be congested with the previous or subsequent message.(I found this extremely annoying) So, to avoid this problem, my code appends the string "#8i8#TERMINATE#" to the end of each string of data to send before sending it.At the other end, the recieving data is split based on this string so you have your individual messages again.Of course, the downside is that you cannot use the string "#8i8#TERMINATE#" in normal data in my code. But I doubt that will be a problem. ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search Link to comment Share on other sites More sharing options...
twitchyliquid64 Posted September 20, 2010 Share Posted September 20, 2010 Ok. What I meant to say was;basically, as you said, TCP appends messages sent in quick succession together.This is an issue for code that looks for specific strings as the string can sometimes be congested with the previous or subsequent message.(I found this extremely annoying) So, to avoid this problem, my code appends the string "#8i8#TERMINATE#" to the end of each string of data to send before sending it.At the other end, the recieving data is split based on this string so you have your individual messages again.Of course, the downside is that you cannot use the string "#8i8#TERMINATE#" in normal data in my code. But I doubt that will be a problem.and the quoted duplicate message was an accident. ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search Link to comment Share on other sites More sharing options...
darkjohn20 Posted September 29, 2010 Share Posted September 29, 2010 When I call _TCP_Client_Create() when no server is present, it doesn't return, it just hangs. What can I do to fix this?This is the function I was hoping to use, but it hangs on the first _TCP_Client_Create():Func _TCPClientCreateEx($sIP, $iPort) Local $hClient = 0, $iRetries = 0, $iMaxRetries = 10 Do ConsoleWrite("Attempting to connect to " & $sIP & ":" & $iPort & "..." & @CRLF) $hClient = _TCP_Client_Create($sIP, $iPort) $iRetries += 1 Until $hClient Or ($iRetries >= $iMaxRetries) If $iRetries >= $iMaxRetries Then ConsoleWrite("Connection to server failed after " & $iRetries & " retries." & @CRLF) Exit ElseIf $hClient Then _TCP_RegisterEvent($hClient, $TCP_CONNECT, "_OnConnect") _TCP_RegisterEvent($hClient, $TCP_DISCONNECT, "_OnDisconnect") _TCP_RegisterEvent($hClient, $TCP_RECEIVE, "_OnReceive") Return $hClient Else ConsoleWrite("Other error while connecting" & @CRLF) Exit EndIf EndFunc Link to comment Share on other sites More sharing options...
Kip Posted September 30, 2010 Author Share Posted September 30, 2010 When I call _TCP_Client_Create() when no server is present, it doesn't return, it just hangs. What can I do to fix this? This is the function I was hoping to use, but it hangs on the first _TCP_Client_Create(): Func _TCPClientCreateEx($sIP, $iPort) Local $hClient = 0, $iRetries = 0, $iMaxRetries = 10 Do ConsoleWrite("Attempting to connect to " & $sIP & ":" & $iPort & "..." & @CRLF) $hClient = _TCP_Client_Create($sIP, $iPort) $iRetries += 1 Until $hClient Or ($iRetries >= $iMaxRetries) If $iRetries >= $iMaxRetries Then ConsoleWrite("Connection to server failed after " & $iRetries & " retries." & @CRLF) Exit ElseIf $hClient Then _TCP_RegisterEvent($hClient, $TCP_CONNECT, "_OnConnect") _TCP_RegisterEvent($hClient, $TCP_DISCONNECT, "_OnDisconnect") _TCP_RegisterEvent($hClient, $TCP_RECEIVE, "_OnReceive") Return $hClient Else ConsoleWrite("Other error while connecting" & @CRLF) Exit EndIf EndFuncDoes it hang, or does it just take a lot of time to return? MailSpons: Fake SMTP server for safe email testing Dutch postcode & address API. Link to comment Share on other sites More sharing options...
darkjohn20 Posted September 30, 2010 Share Posted September 30, 2010 (edited) It's never returned for me. I've waited minutes, but nothing happened. I even opened the server while it was trying to connect to see if it would pick it up and it didn't. Is there a way to change the timeout in the UDF?And also, is there a way to get around $hSocket returning 0 when a client disconnects?;... _TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "_OnDisconnect") ;... Func _OnDisconnect($hSocket, $iError) ConsoleWrite($hSocket) ;Writes "0" EndFunc Edited September 30, 2010 by darkjohn20 Link to comment Share on other sites More sharing options...
viroman Posted October 3, 2010 Share Posted October 3, 2010 (edited) Hello Kip, thank you very much for your work. I wanted to create something like port forwarder with your library, but i got some problems. Also, i need server and client connections in same script to do that.. and the connection to forwarded remote host can not be established after server was firstly started, at least not as event. Why does that happen? Is it possible to create connection sockets after server was started? In this example the function "Connected" doesn't get called if hServer gets created, also $hServer = _TCP_Server_Create(88); Of course, if i uncomment it, it works, but not working is not what i need Why does that happen, how to fix? Thanky you! expandcollapse popup#include "TCP.au3" $hServer = _TCP_Server_Create(88); ;Comment hServer and it works then? Why? ;_TCP_RegisterEvent($hServer, $TCP_NEWCLIENT, "NewClientLocal"); ;_TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "DisconnectedLocal"); ;_TCP_RegisterEvent($hServer, $TCP_RECEIVE, "ReceivedLocal"); $hClient = _TCP_Client_Create("62.153.159.92", 80) ConsoleWrite('->Client handler created!' & @CRLF) _TCP_RegisterEvent($hClient, $TCP_RECEIVE, "Received") _TCP_RegisterEvent($hClient, $TCP_CONNECT, "Connected") _TCP_RegisterEvent($hClient, $TCP_DISCONNECT, "Disconnected") While 1 Sleep(1000) WEnd Func Connected($hSocket, $iError); If not $iError Then; If there is no error... ConsoleWrite('->Client connected!' & @CRLF) ;Debug, for fun :P Else; ,else... ConsoleWrite('->Client not connected!' & @CRLF) ;Debug, for fun :P EndIf EndFunc Func Received($hSocket, $sReceived, $iError) ToolTip("CLIENT: We received this: "& $sReceived, 10,10) EndFunc Func Disconnected($hSocket, $iError) ConsoleWrite('->Client; connection closed or lost!' & @CRLF) EndFunc Edited October 3, 2010 by viroman Link to comment Share on other sites More sharing options...
viroman Posted October 4, 2010 Share Posted October 4, 2010 I wanted to post my quick and dirty method, i have copied the file TCP.au3 to TCPc.au3, so that c on the end stays for client version, and than i have renamed all functions and variables on same way, with c on the end, and then i have only commented out ;TCPStartup() in TCPc.au3 and than in my main file i have included them on the beginning #include "TCP.au3" #include "TCPc.au3" And renamed all clients calls like so $hClient = _TCP_Client_Createc("62.153.159.92", 80); Create the client. Which will connect to the local ip address on port 88 ConsoleWrite('->Client handler created!' & @CRLF) ;Debug, for fun :P _TCP_RegisterEventc($hClient, $TCP_RECEIVEc, "Received"); Function "Received" will get called when something is received _TCP_RegisterEventc($hClient, $TCP_CONNECTc, "Connected"); And func "Connected" will get called when the client is connected. _TCP_RegisterEventc($hClient, $TCP_DISCONNECTc, "Disconnected"); And "Disconnected" will get called when the server disconnects us, or when the connection is lost. Now server gets created and clients too.. Quick and dirty, i know, takes 15 minutes, but saves all other troubles.. Now may be you know, how to fix them on your way. Link to comment Share on other sites More sharing options...
viroman Posted October 4, 2010 Share Posted October 4, 2010 May be someone will need it quick and dirty _TCP_RegisterEventServer _TCP_RegisterEventClient From now on i use these commands separately to register events for client and server, else it wasn't working before. expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.0.0 Author: Kip Script Function: TCP UDF v3 #ce ---------------------------------------------------------------------------- ; Script Start - Add your code below here #cs Functions: _TCP_Server_Create($iPort, $sIP="0.0.0.0") _TCP_Server_Broadcast($sData) _TCP_Server_ClientList() _TCP_Server_ClientIP($hSocket) _TCP_Server_DisconnectClient($hSocket) _TCP_Server_Stop() _TCP_Client_Create($sIP , $iPort) _TCP_Client_Stop($hSocket) _TCP_Send($hSocket, $sText) _TCP_RegisterEventServer($hSocket, $iEvent, $sFunction) _TCP_RegisterEventClient($hSocket, $iEvent, $sFunction) Register event values: $TCP_SEND ; Function ($hSocket, $iError) $TCP_RECEIVE ; Function ($hSocket, $sReceived, $iError) $TCP_CONNECT ; Function ($hSocket, $iError) => Client only $TCP_DISCONNECT ; Function ($hSocket, $iError) $TCP_NEWCLIENT ; Function ($hSocket, $iError) => Server only #ce Global Const $FD_READ = 1 Global Const $FD_WRITE = 2 Global Const $FD_OOB = 4 Global Const $FD_ACCEPT = 8 Global Const $FD_CONNECT = 16 Global Const $FD_CLOSE = 32 Global $hWs2_32 = -1 Global Const $TCP_SEND = 1 Global Const $TCP_RECEIVE = 2 Global Const $TCP_CONNECT = 4 Global Const $TCP_DISCONNECT = 8 Global Const $TCP_NEWCLIENT = 16 TCPStartup() Global Const $__TCP_WINDOW = GUICreate("Async Sockets UDF") Global $__TCP_SOCKETS[1][7] Global $__TCP_SOCKETSc[1][7]; //added for separat client ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_Create ; Description ...: Initializes the server. ; Syntax.........: _TCP_Server_Create($iPort, $sIP="0.0.0.0") ; Parameters ....: $iPort - The port number the server should listen to. ; $sIP - IP address. (Default = "0.0.0.0") ; Return values .: The socket handle. ; Author ........: Kip ; Modified.......: ; Remarks .......: Only 1 server can be created per script. ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_Create($iPort, $sIP="0.0.0.0") Local $hListenSocket = ___ASocket() ___ASockSelect( $hListenSocket, $__TCP_WINDOW, 0x0400, $FD_ACCEPT) GUIRegisterMsg( 0x0400, "___TCP_OnAccept" ) ___ASockListen( $hListenSocket, $sIP, $iPort ) $__TCP_SOCKETS[0][0] = $hListenSocket $__TCP_SOCKETS[0][1] = 0x0400 Return $hListenSocket EndFunc Func ___TCP_OnAccept($hWnd, $iMsgID, $WParam, $LParam) Local $hSocket = $WParam Local $iError = ___HiWord( $LParam ) Local $iEvent = ___LoWord( $LParam ) Local $hClient, $uBound Abs($hWnd) ; Stupid AU3Check... If $iMsgID = $__TCP_SOCKETS[0][1] Then If $iEvent = $FD_ACCEPT Then If Not $iError Then ReDim $__TCP_SOCKETS[UBound($__TCP_SOCKETS)+1][7] $uBound = UBound($__TCP_SOCKETS) $hClient = TCPAccept($hSocket) ___ASockSelect($hClient, $__TCP_WINDOW, 0x0400 + $uBound - 1, BitOR($FD_READ, $FD_WRITE, $FD_CLOSE)) GUIRegisterMsg(0x0400 + $uBound - 1, "___TCP_Server_OnSocketEvent" ) $__TCP_SOCKETS[UBound($__TCP_SOCKETS)-1][0] = $hClient $__TCP_SOCKETS[UBound($__TCP_SOCKETS)-1][1] = 0x0400 + $uBound - 1 Call($__TCP_SOCKETS[0][6], $hClient, $iError) Else Call($__TCP_SOCKETS[0][6], 0, $iError) EndIf ElseIf $iEvent = $FD_CONNECT Then Call($__TCP_SOCKETS[0][4], $hSocket, $iError) EndIf EndIf EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Client_Stop ; Description ...: Stops the client. ; Syntax.........: _TCP_Client_Stop($hSocket) ; Parameters ....: $hSocket - Client socket. ; Return values .: Success - True ; Failure - False ; Author ........: Kip ; Modified.......: ; Remarks .......: The client socket is the return value of _TCP_Client_Create(). ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Client_Stop($hSocket) Local $iElement, $i $iElement = 0 For $i = 1 to UBound($__TCP_SOCKETSc)-1 If $__TCP_SOCKETSc[$i][0] = $hSocket Then $iElement = $i ExitLoop EndIf Next If $iElement Then ___ASockShutdown($__TCP_SOCKETSc[$iElement][0]) TCPCloseSocket($__TCP_SOCKETSc[$iElement][0]) ___ArrayDelete($__TCP_SOCKETSc, $iElement) Return True EndIf Return False EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_Stop ; Description ...: Stops the server, and closes all client connections. ; Syntax.........: _TCP_Server_Stop() ; Parameters ....: ; Return values .: True ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_Stop() Local $i ___ASockShutdown($__TCP_SOCKETS[0][0]) TCPCloseSocket($__TCP_SOCKETS[0][0]) $__TCP_SOCKETS[0][0] = "" $__TCP_SOCKETS[0][1] = "" $__TCP_SOCKETS[0][2] = "" $__TCP_SOCKETS[0][3] = "" $__TCP_SOCKETS[0][4] = "" $__TCP_SOCKETS[0][5] = "" $__TCP_SOCKETS[0][6] = "" For $i = UBound($__TCP_SOCKETS)-1 to 1 Step -1 ___ArrayDelete($__TCP_SOCKETS, $i) Next Return True EndFunc Func ___TCP_Server_OnSocketEvent( $hWnd, $iMsgID, $WParam, $LParam ) Local $hSocket = $WParam Local $iError = ___HiWord( $LParam ) Local $iEvent = ___LoWord( $LParam ) Local $sDataBuff, $iElement, $i Abs($hWnd) $hSocket = 0 $iElement = 0 For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][1] = $iMsgID Then $hSocket = $__TCP_SOCKETS[$i][0] $iElement = $i ExitLoop EndIf Next If $hSocket Then Switch $iEvent Case $FD_READ $sDataBuff = TCPRecv($hSocket, 1024) Call($__TCP_SOCKETS[0][2], $hSocket, $sDataBuff, $iError) Case $FD_WRITE Call($__TCP_SOCKETS[0][3], $hSocket, $iError) Case $FD_CLOSE ___ASockShutdown($hSocket) TCPCloseSocket($hSocket) Call($__TCP_SOCKETS[0][5], $hSocket, $iError) ___ArrayDelete($__TCP_SOCKETS, $iElement) EndSwitch EndIf EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_DisconnectClient ; Description ...: Disconnects a client of the server. ; Syntax.........: _TCP_Server_DisconnectClient($hSocket) ; Parameters ....: $hSocket - Client socket. ; Return values .: Success - True ; Failure - False ; Author ........: Kip ; Modified.......: ; Remarks .......: The client socket is the $hSocket parameter of a _TCP_RegisterEvent callback function. ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_DisconnectClient($hSocket) Local $iElement, $i $iElement = 0 For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] = $hSocket Then $iElement = $i ExitLoop EndIf Next If $iElement Then ___ASockShutdown($hSocket) TCPCloseSocket($hSocket) ___ArrayDelete($__TCP_SOCKETS, $iElement) Return True EndIf Return False EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_ClientList ; Description ...: Returns the sockets of all connected clients. ; Syntax.........: _TCP_Server_ClientList() ; Parameters ....: ; Return values .: An 1 dimensional array of all connected clients. ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_ClientList() Local $aReturn[1], $i For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] Then ReDim $aReturn[UBound($aReturn)+1] $aReturn[UBound($aReturn)-1] = $__TCP_SOCKETS[$i][0] EndIf Next $aReturn[0] = UBound($aReturn)-1 Return $aReturn EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_Broadcast ; Description ...: Sends data to all connected clients. ; Syntax.........: _TCP_Server_Broadcast($sData) ; Parameters ....: $sData - The data to send. ; Return values .: True ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_Broadcast($sData) Local $i For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] Then TCPSend($__TCP_SOCKETS[$i][0], $sData) Next Return True EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Client_Create ; Description ...: Creates a new client. ; Syntax.........: _TCP_Client_Create($sIP , $iPort) ; Parameters ....: $sIP - The IP address to connect to. ; $iPort - Port on which the created socket will be connected. ; Return values .: Client socket handle. ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Client_Create($sIP , $iPort) ReDim $__TCP_SOCKETSc[UBound($__TCP_SOCKETSc)+1][7] local $hSocket = ___ASocket() $__TCP_SOCKETSc[UBound($__TCP_SOCKETSc)-1][0] = $hSocket $__TCP_SOCKETSc[UBound($__TCP_SOCKETSc)-1][1] = 0x0400 + (UBound($__TCP_SOCKETSc)-1) ___ASockSelect( $hSocket, $__TCP_WINDOW, 0x0400 + (UBound($__TCP_SOCKETSc)-1), BitOR( $FD_READ, $FD_WRITE, $FD_CONNECT, $FD_CLOSE ) ) GUIRegisterMsg( 0x0400 + (UBound($__TCP_SOCKETSc)-1), "___TCP_Client_OnSocketEvent" ) ___ASockConnect( $hSocket, $sIP, $iPort ) Return $hSocket EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_RegisterEvent ; Description ...: Registers an event. ; Syntax.........: _TCP_RegisterEvent($hSocket, $iEvent, $sFunction) ; Parameters ....: $hSocket - Socket of the server or a client. ; $iEvent - Event number. It can be any these values: ; * $TCP_SEND ; * $TCP_RECEIVE ; * $TCP_CONNECT => Client only ; * $TCP_DISCONNECT ; * $TCP_NEWCLIENT => Server only ; Return values .: Success - True ; Failure - False ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_RegisterEventServer($hSocket, $iEvent, $sFunction) Local $iSelected = 0 Local $i If $__TCP_SOCKETS[0][0] Then $iSelected = 0 Else For $i = 0 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] = $hSocket Then $iSelected = $i ExitLoop EndIf Next If Not $iSelected Then Return 0 EndIf Switch $iEvent Case $TCP_SEND $__TCP_SOCKETS[$iSelected][3] = $sFunction Case $TCP_RECEIVE $__TCP_SOCKETS[$iSelected][2] = $sFunction Case $TCP_CONNECT $__TCP_SOCKETS[$iSelected][4] = $sFunction Case $TCP_DISCONNECT $__TCP_SOCKETS[$iSelected][5] = $sFunction Case $TCP_NEWCLIENT $__TCP_SOCKETS[$iSelected][6] = $sFunction Case Else Return False EndSwitch Return True EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_ClientIP ; Description ...: Converts a client socket handle to IP address. ; Syntax.........: _TCP_Server_ClientIP($hSocket) ; Parameters ....: $hSocket - Client socket handle. ; Return values .: A string with the IP address. ; Author ........: Unknown ; Modified.......: Kip ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_ClientIP($hSocket) Local $pSocketAddress, $aReturn $pSocketAddress = DllStructCreate("short;ushort;uint;char[8]") $aReturn = DllCall("Ws2_32.dll", "int", "getpeername", "int", $hSocket, "ptr", DllStructGetPtr($pSocketAddress), "int*", DllStructGetSize($pSocketAddress)) If @error Or $aReturn[0] <> 0 Then Return 0 $aReturn = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($pSocketAddress, 3)) If @error Then Return 0 $pSocketAddress = 0 Return $aReturn[0] EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Send ; Description ...: Sends data to a server or client. ; Syntax.........: _TCP_Send($hSocket, $sText) ; Parameters ....: $hSocket - Client or server socket handle. ; $sText - Data to send. ; Return values .: ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Send($hSocket, $sText) Return TCPSend($hSocket, $sText) EndFunc Func ___TCP_Client_OnSocketEvent( $hWnd, $iMsgID, $WParam, $LParam ) Local $iError = ___HiWord( $LParam ) Local $iEvent = ___LoWord( $LParam ) Local $hSocket, $iElement, $i, $sDataBuff Abs($hWnd) Abs($WParam) $hSocket = 0 $iElement = 0 For $i = 1 to UBound($__TCP_SOCKETSc)-1 If $__TCP_SOCKETSc[$i][1] = $iMsgID Then $hSocket = $__TCP_SOCKETSc[$i][0] $iElement = $i ExitLoop EndIf Next If $hSocket Then Switch $iEvent Case $FD_READ; Data has arrived! $sDataBuff = TCPRecv( $hSocket, 1024) Call($__TCP_SOCKETSc[$i][2], $hSocket, $sDataBuff, $iError) $sDataBuff = "" Case $FD_WRITE Call($__TCP_SOCKETSc[$i][3], $hSocket, $iError) Case $FD_CONNECT Call($__TCP_SOCKETSc[$i][4], $hSocket, $iError) Case $FD_CLOSE ___ASockShutdown( $hSocket ) TCPCloseSocket( $hSocket ) Call($__TCP_SOCKETSc[$i][5], $hSocket, $iError) ___ArrayDelete($__TCP_SOCKETSc, $iElement) EndSwitch EndIf EndFunc Func _TCP_RegisterEventClient($hSocket, $iEvent, $sFunction) Local $iSelected = 0 Local $i If $__TCP_SOCKETSc[0][0] Then $iSelected = 0 Else For $i = 0 to UBound($__TCP_SOCKETSc)-1 If $__TCP_SOCKETSc[$i][0] = $hSocket Then $iSelected = $i ExitLoop EndIf Next If Not $iSelected Then Return 0 EndIf Switch $iEvent Case $TCP_SEND $__TCP_SOCKETSc[$iSelected][3] = $sFunction Case $TCP_RECEIVE $__TCP_SOCKETSc[$iSelected][2] = $sFunction Case $TCP_CONNECT $__TCP_SOCKETSc[$iSelected][4] = $sFunction Case $TCP_DISCONNECT $__TCP_SOCKETSc[$iSelected][5] = $sFunction Case $TCP_NEWCLIENT $__TCP_SOCKETSc[$iSelected][6] = $sFunction Case Else Return False EndSwitch Return True EndFunc ;================================================================================================================== ; ; Zatorg's Asynchronous Sockets UDF Starts from here. ; ;================================================================================================================== Func ___ASocket($iAddressFamily = 2, $iType = 1, $iProtocol = 6) If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $hSocket = DllCall($hWs2_32, "uint", "socket", "int", $iAddressFamily, "int", $iType, "int", $iProtocol) If @error Then SetError(1, @error) Return -1 EndIf If $hSocket[ 0 ] = -1 Then SetError(2, ___WSAGetLastError()) Return -1 EndIf Return $hSocket[ 0 ] EndFunc ;==>_ASocket Func ___ASockShutdown($hSocket) If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $iRet = DllCall($hWs2_32, "int", "shutdown", "uint", $hSocket, "int", 2) If @error Then SetError(1, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then SetError(2, ___WSAGetLastError()) Return False EndIf Return True EndFunc ;==>_ASockShutdown Func ___ASockClose($hSocket) If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $iRet = DllCall($hWs2_32, "int", "closesocket", "uint", $hSocket) If @error Then SetError(1, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then SetError(2, ___WSAGetLastError()) Return False EndIf Return True EndFunc ;==>_ASockClose Func ___ASockSelect($hSocket, $hWnd, $uiMsg, $iEvent) If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $iRet = DllCall( _ $hWs2_32, _ "int", "WSAAsyncSelect", _ "uint", $hSocket, _ "hwnd", $hWnd, _ "uint", $uiMsg, _ "int", $iEvent _ ) If @error Then SetError(1, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then SetError(2, ___WSAGetLastError()) Return False EndIf Return True EndFunc ;==>_ASockSelect ; Note: you can see that $iMaxPending is set to 5 by default. ; IT DOES NOT MEAN THAT DEFAULT = 5 PENDING CONNECTIONS ; 5 == SOMAXCONN, so don't worry be happy Func ___ASockListen($hSocket, $sIP, $uiPort, $iMaxPending = 5); 5 == SOMAXCONN => No need to change it. Local $iRet Local $stAddress If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) $stAddress = ___SockAddr($sIP, $uiPort) If @error Then SetError(@error, @extended) Return False EndIf $iRet = DllCall($hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($stAddress), "int", DllStructGetSize($stAddress)) If @error Then SetError(3, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then $stAddress = 0; Deallocate SetError(4, ___WSAGetLastError()) Return False EndIf $iRet = DllCall($hWs2_32, "int", "listen", "uint", $hSocket, "int", $iMaxPending) If @error Then SetError(5, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then $stAddress = 0; Deallocate SetError(6, ___WSAGetLastError()) Return False EndIf Return True EndFunc ;==>_ASockListen Func ___ASockConnect($hSocket, $sIP, $uiPort) Local $iRet Local $stAddress If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) $stAddress = ___SockAddr($sIP, $uiPort) If @error Then SetError(@error, @extended) Return False EndIf $iRet = DllCall($hWs2_32, "int", "connect", "uint", $hSocket, "ptr", DllStructGetPtr($stAddress), "int", DllStructGetSize($stAddress)) If @error Then SetError(3, @error) Return False EndIf $iRet = ___WSAGetLastError() If $iRet = 10035 Then; WSAEWOULDBLOCK Return True; Asynchronous connect attempt has been started. EndIf SetExtended(1); Connected immediately Return True EndFunc ;==>_ASockConnect ; A wrapper function to ease all the pain in creating and filling the sockaddr struct Func ___SockAddr($sIP, $iPort, $iAddressFamily = 2) Local $iRet Local $stAddress If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) $stAddress = DllStructCreate("short; ushort; uint; char[8]") If @error Then SetError(1, @error) Return False EndIf DllStructSetData($stAddress, 1, $iAddressFamily) $iRet = DllCall($hWs2_32, "ushort", "htons", "ushort", $iPort) DllStructSetData($stAddress, 2, $iRet[ 0 ]) $iRet = DllCall($hWs2_32, "uint", "inet_addr", "str", $sIP) If $iRet[ 0 ] = 0xffffffff Then; INADDR_NONE $stAddress = 0; Deallocate SetError(2, ___WSAGetLastError()) Return False EndIf DllStructSetData($stAddress, 3, $iRet[ 0 ]) Return $stAddress EndFunc ;==>__SockAddr Func ___WSAGetLastError() If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $iRet = DllCall($hWs2_32, "int", "WSAGetLastError") If @error Then ;ConsoleWrite("+> _WSAGetLastError(): WSAGetLastError() failed. Script line number: " & @ScriptLineNumber & @CRLF) SetExtended(1) Return 0 EndIf Return $iRet[ 0 ] EndFunc ;==>_WSAGetLastError ; Got these here: ; http://www.autoitscript.com/forum/index.php?showtopic=5620&hl=MAKELONG Func ___MakeLong($LoWord, $HiWord) Return BitOR($HiWord * 0x10000, BitAND($LoWord, 0xFFFF)); Thanks Larry EndFunc ;==>_MakeLong Func ___HiWord($Long) Return BitShift($Long, 16); Thanks Valik EndFunc ;==>_HiWord Func ___LoWord($Long) Return BitAND($Long, 0xFFFF); Thanks Valik EndFunc ;==>_LoWord ; ========================================= Array functions ; #FUNCTION# ==================================================================================================================== ; Name...........: _ArrayDelete ; Description ...: Deletes the specified element from the given array. ; Syntax.........: _ArrayDelete(ByRef $avArray, $iElement) ; Parameters ....: $avArray - Array to modify ; $iElement - Element to delete ; Return values .: Success - New size of the array ; Failure - 0, sets @error to: ; |1 - $avArray is not an array ; |3 - $avArray has too many dimensions (only up to 2D supported) ; |(2 - Deprecated error code) ; Author ........: Cephas <cephas at clergy dot net> ; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - array passed ByRef, Ultima - 2D arrays supported, reworked function (no longer needs temporary array; faster when deleting from end) ; Remarks .......: If the array has one element left (or one row for 2D arrays), it will be set to "" after _ArrayDelete() is used on it. ; Related .......: _ArrayAdd, _ArrayInsert, _ArrayPop, _ArrayPush ; Link ..........; ; Example .......; Yes ; =============================================================================================================================== Func ___ArrayDelete(ByRef $avArray, $iElement) If Not IsArray($avArray) Then Return SetError(1, 0, 0) Local $iUBound = UBound($avArray, 1) - 1 If Not $iUBound Then $avArray = "" Return 0 EndIf ; Bounds checking If $iElement < 0 Then $iElement = 0 If $iElement > $iUBound Then $iElement = $iUBound ; Move items after $iElement up by 1 Switch UBound($avArray, 0) Case 1 For $i = $iElement To $iUBound - 1 $avArray[$i] = $avArray[$i + 1] Next ReDim $avArray[$iUBound] Case 2 Local $iSubMax = UBound($avArray, 2) - 1 For $i = $iElement To $iUBound - 1 For $j = 0 To $iSubMax $avArray[$i][$j] = $avArray[$i + 1][$j] Next Next ReDim $avArray[$iUBound][$iSubMax + 1] Case Else Return SetError(3, 0, 0) EndSwitch Return $iUBound EndFunc ;==>_ArrayDelete Link to comment Share on other sites More sharing options...
viroman Posted October 4, 2010 Share Posted October 4, 2010 (edited) Nope, nothing works, the error seems to be very deeply, also forget the code above.. 2 Kip, i have reversed your code little bit and you have choosen wrong way to go that in reality doesn't let you to use many simultaneous connections, only one conenction works fine, snd any others do not work.. Why? Because you are registering with GUIRegisterMsg the message IDs from the number of actual connections(computed by size) beginning by 1024(0x0400) Let say, i have connected with the client and got 1025 ID ( 1024 + 1 ) because array has 1 element Then i have again connected with the client and got 1026 ID ( 1024 + 2 ) because array has 2 elements than again new connection 1027 ID ( 1024 + 3 ) because array has 3 elements and so on... You are computing always array size and add it to 1024 or however.. New connection means new array element.. It may be ok, if no one server/client disconnects, but as soon one is disconnecting, you begin to produce errornous handling. Why??? By taking example above, let say, 1025,1026,1027, also 3 elements, and now ID 1025 disconnects or connection get lost... now we have 2 elements in our array, because you are deleting it... What do we have now? We have IDs 1026, 1027, also two elements, now new client will connect... We add again 1024 plus size of array, also two, 1024 + 2 = 1026 (so as you do it in your code) Now what do we do, if we are doing it so???? We overwrite also ID 1026 with the socket of new connection so that event from old connection on old ID 1026 will never be called again, but only new event for new conenction. So, now i try to forget about computing array size and let them just increase the number of messages as soon GUIRegisterMsg is called. Well, may be it get rid of such errors, but i am poor programmer, therefore not sure, if i do it correctly Edited January 16, 2017 by viroman Link to comment Share on other sites More sharing options...
kristo Posted October 21, 2010 Share Posted October 21, 2010 For my purposes everything works fine so far. Thanks for the good work However it seems you're using the win32 dll for your calls. What about 64 bit windows or Windows 7. Does is run? Cheap, Fast, Good - Choose any two Link to comment Share on other sites More sharing options...
twitchyliquid64 Posted October 22, 2010 Share Posted October 22, 2010 (edited) Nope, nothing works, the error seems to be very deeply, also forget the code above..2 Kip, i have reversed your code little bit and you have choosen wrong way to go that in reality doesn't let you to use many simultaneous connections, only one conenction works fine, snd any others do not work..Why?Because you are registering with GUIRegisterMsg the message IDs from the number of actual connections(computed by size) beginning by 1024(0x0400)Let say, i have connected with the client and got 1025 ID ( 1024 + 1 ) because array has 1 elementThan i have again connected with the client and got 1026 ID ( 1024 + 2 ) because array has 2 elementsthan again new connection 1027 ID ( 1024 + 3 ) because array has 3 elementsand so on...You are computing always array size and add it to 1024 or however..New connection means new array element..It may be ok, if no one server/client disconnects, but as soon one is disconnecting, your begint to produce errornous handling.Why???By taking example above, let say, 1025,1026,1027, also 3 elements, and now ID 1025 disconnects or connection get lost...now we have 2 elements in our array, because you are deleting it... What do we have now?We have IDs 1026, 1027, also two elements, now new client will connect...We add again 1024 plus size of array, also two, 1024 + 2 = 1026 (so as you do it in your code)Now what do we do, if we are doing it so????We overwrite also ID 1026 with the socket of new connection so that event from old connection on old ID 1026 will never be called again, but only new event for new conenction.So, now i try to forget about computing array size and let them just increase the number of messages as soon GUIRegisterMsg is called. Well, may be it get rid of such errors, but i am poor programmer, therefore not sure, if i do it correctly Dude I re-wrote Kips UDF to work with a Client and Server in the same script. Note that it is designed for a P2P Node, and thus is a bit more complicated for your needs. So turn off Bootstrapping and ignore a good deal of the functions I have added. If I remember correctly, it's called P2P TCP UDF, Event Driven! or words to that effect. Or you could click on my profile and look at my topics.Also that problem in the quote above (if it is indeed a problem) will not occur in my script. Edited October 22, 2010 by hyperzap ongoing projects:-firestorm: Largescale P2P Social NetworkCompleted Autoit Programs/Scripts: Variable Pickler | Networked Streaming Audio (in pure autoIT) | firenet p2p web messenger | Proxy Checker | Dynamic Execute() Code Generator | P2P UDF | Graph Theory Proof of Concept - Breadth First search Link to comment Share on other sites More sharing options...
matwachich Posted February 1, 2011 Share Posted February 1, 2011 Think i found a bug: When the client is loosing the server (cause of server shutdown or else), the client bugs when trying ti reconnect. After searching a few in your code, i found that the function _ArrayDelete, that alters the $__TCK_SOCKETS array, makes the array empty string ($avArray = ""), so i commented that line (; $avArray = ""), and every thing worked fine! If Not $iUBound Then ; $avArray = "" ; This is the KEY to the bug that when the client lost connection ; with the server, it cannot reconnect becaut $__TCP_SOCKETS became ; not an array Return 0 EndIf Link to comment Share on other sites More sharing options...
qty Posted April 29, 2011 Share Posted April 29, 2011 hey there, hope i can get some help polling this dated thread. i found your topic when i ran into some strange events using tcp sockets. here is what i've done. for getting into sockets i made a, very basic sniffer, and i did this with writing a bridge script which connects to a server and, in the same time, waits for client. (server and client are not written in auto it, only the bridge is) This means, the bridge is a server and a client at the same time. At first, it does nothing but directing incoming data from the server to the client and vice versa. That worked very nice, i even couldnt recognize any lag. In the second step i wanted to let a second client, this time written in autoit, connect to the "bridge". This second client should get both, the stream which comes from the server and the one that comes from the original client and it was this autoit client which should do any magic parsing etc. And this is where the strange stuff began to roll. first thing was, the client <-> bridge <-> server traffic still worked out well, also the self written autoit client was able to connect to the bridge. When testing send() it gave me back that data has been sent, but no matter what i tried, i couldnt fetch any recieved data, not with the bridge, nor with the autoit client. strange thing is: it worked when i ran the client first and let it loop the TCPconnect(). While the autoit client ran in this loop, i had to start the server(bridge) and THEN, and ONLY then it worked that the bridge also transfered its data not only to the origin client but also to my autoit client. I thought that might be cause of the use server and client in one script and so i wrote a basic server + client in autoit, but the problem remained the same. I had to run the client first, let it loop TCPconnect(), else no data is recieved. Again: There where no errors in establishing the connection, and TCPsend() gave me back that data has been sent. But there was no way to access the recv = TCPrecv() when i started the server first, only when i started the client first. Now i found your thread and i hope a can fix some stuff with your udf. In your entry post you write: "You can't create a server and a client in the same script." Does that mean its entirely not possible, as i did and ran into trouble, to have a server and a client in one script or are you talking a about a server + client that wants to talk with "itself"? I now red this entire thread and there are some ppl talking about bugs, and different versions. Whats the most uptodate version of your udf? The one in the entry post? Are there any other, maybe more enhanced, versions of multiclient frameworks? Any hints about what i could have messed up? thx everyone in advance, so far this looks really tasty. qty Link to comment Share on other sites More sharing options...
johnnyd Posted August 24, 2011 Share Posted August 24, 2011 (edited) Hello there!! I have a problem..I used the script tcp.au3 in the past in an application..But i see now that it doesn't work in all the situations..It depends on the pc it runs (server script) or maybe on the router(port forwarding).. Right now, i can't make them work.. As a result I'm not sure what the problem is.. PS. In my application the client is a development board that connects to a server and sends some data that get stored to a DB.. Any help is appreciated.. server-script expandcollapse popup#include "TCP.au3" #include "mysql.au3" #include "Date1.au3" #include-once $UserName = "myuser" $Password = "mypsw" $Database = "diplwmatiki" $MySQLServerName = "localhost" $SQLInstance = _MySQLConnect($UserName,$Password,$Database,$MySQLServerName) ToolTip("SERVER: Creating server...",10,30) $hServer = _TCP_Server_Create(88); A server. Tadaa! _TCP_RegisterEvent($hServer, $TCP_RECEIVE, "Received"); Function "Received" will get called when something is received _TCP_RegisterEvent($hServer, $TCP_NEWCLIENT, "NewClient"); Whooooo! Now, this function (NewClient) get's called when a new client connects to the server. _TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "Disconnect"); And this,... this will get called when a client disconnects. While 1 WEnd Func NewClient($hSocket, $iError); Yo, check this out! It's a $iError parameter! (In case you didn't noticed: It's in every function) ToolTip("SERVER: New client connected."&@CRLF&"Server sends this: Bleh!",10,30) _TCP_Send($hSocket, "Bleh!"); Sending: "Bleh!" to the new client. (Yes, that's right: $hSocket is the socket of the new client.) EndFunc Func Received($hSocket, $sReceived, $iError); And we also registered this! Our homemade do-it-yourself function gets called when something is received. ToolTip("CLIENT: I send this: "& $sReceived, 10,10); (and we'll display it) Insert_MySQL($sReceived); EndFunc Func Insert_MySQL($sReceived) $Data = "" $Data = $sReceived $Pliroforia = StringSplit($Data, " ") $Cur_Date = _NowCalcDate() $Cur_Time = _NowCalc() Dim $ColumnNames[7] $ColumnNames[0]= "id_measure" $ColumnNames[1]= "id_node" $ColumnNames[2]= "date" $ColumnNames[3]= "time" $ColumnNames[4]= "chlorio" $ColumnNames[5]= "roi" $ColumnNames[6]= "" Dim $NewMeasurement[7] $NewMeasurement[0]="" $NewMeasurement[1]=$Pliroforia[1] $NewMeasurement[2]=$Cur_Date $NewMeasurement[3]=$Cur_Time $NewMeasurement[4]=$Pliroforia[2] $NewMeasurement[5]=$Pliroforia[3] $NewMeasurement[6]="" _AddRecord($SQLInstance,"measurement",$ColumnNames,$NewMeasurement) EndFunc Func Disconnect($hSocket, $iError); Damn, we lost a client. Time of death: @Hour & @Min & @Sec :P ToolTip("SERVER: Client disconnected.",10,30); Placing a tooltip right under the tooltips of the client. EndFunc TCP script (i only added IP and port) expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.0.0 Author: Kip Script Function: TCP UDF v3 #ce ---------------------------------------------------------------------------- ; Script Start - Add your code below here #cs Functions: _TCP_Server_Create($iPort, $sIP="0.0.0.0") _TCP_Server_Broadcast($sData) _TCP_Server_ClientList() _TCP_Server_ClientIP($hSocket) _TCP_Server_DisconnectClient($hSocket) _TCP_Server_Stop() _TCP_Client_Create($sIP , $iPort) _TCP_Client_Stop($hSocket) _TCP_Send($hSocket, $sText) _TCP_RegisterEvent($hSocket, $iEvent, $sFunction) Register event values: $TCP_SEND ; Function ($hSocket, $iError) $TCP_RECEIVE ; Function ($hSocket, $sReceived, $iError) $TCP_CONNECT ; Function ($hSocket, $iError) => Client only $TCP_DISCONNECT ; Function ($hSocket, $iError) $TCP_NEWCLIENT ; Function ($hSocket, $iError) => Server only #ce Global Const $FD_READ = 1 Global Const $FD_WRITE = 2 Global Const $FD_OOB = 4 Global Const $FD_ACCEPT = 8 Global Const $FD_CONNECT = 16 Global Const $FD_CLOSE = 32 Global $hWs2_32 = -1 Global Const $TCP_SEND = 1 Global Const $TCP_RECEIVE = 2 Global Const $TCP_CONNECT = 4 Global Const $TCP_DISCONNECT = 8 Global Const $TCP_NEWCLIENT = 16 TCPStartup() Global Const $__TCP_WINDOW = GUICreate("Async Sockets UDF") Global $__TCP_SOCKETS[1][7] ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_Create ; Description ...: Initializes the server. ; Syntax.........: _TCP_Server_Create($iPort, $sIP="0.0.0.0") ; Parameters ....: $iPort - The port number the server should listen to. ; $sIP - IP address. (Default = "0.0.0.0") ; Return values .: The socket handle. ; Author ........: Kip ; Modified.......: ; Remarks .......: Only 1 server can be created per script. ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_Create($iPort=88, $sIP="46.12.209.81") Local $hListenSocket = ___ASocket() ___ASockSelect( $hListenSocket, $__TCP_WINDOW, 0x0400, $FD_ACCEPT) GUIRegisterMsg( 0x0400, "___TCP_OnAccept" ) ___ASockListen( $hListenSocket, $sIP, $iPort ) $__TCP_SOCKETS[0][0] = $hListenSocket $__TCP_SOCKETS[0][1] = 0x0400 Return $hListenSocket EndFunc Func ___TCP_OnAccept($hWnd, $iMsgID, $WParam, $LParam) Local $hSocket = $WParam Local $iError = ___HiWord( $LParam ) Local $iEvent = ___LoWord( $LParam ) Local $hClient, $uBound Abs($hWnd) ; Stupid AU3Check... If $iMsgID = $__TCP_SOCKETS[0][1] Then If $iEvent = $FD_ACCEPT Then If Not $iError Then ReDim $__TCP_SOCKETS[UBound($__TCP_SOCKETS)+1][7] $uBound = UBound($__TCP_SOCKETS) $hClient = TCPAccept($hSocket) ___ASockSelect($hClient, $__TCP_WINDOW, 0x0400 + $uBound - 1, BitOR($FD_READ, $FD_WRITE, $FD_CLOSE)) GUIRegisterMsg(0x0400 + $uBound - 1, "___TCP_Server_OnSocketEvent" ) $__TCP_SOCKETS[UBound($__TCP_SOCKETS)-1][0] = $hClient $__TCP_SOCKETS[UBound($__TCP_SOCKETS)-1][1] = 0x0400 + $uBound - 1 Call($__TCP_SOCKETS[0][6], $hClient, $iError) Else Call($__TCP_SOCKETS[0][6], 0, $iError) EndIf ElseIf $iEvent = $FD_CONNECT Then Call($__TCP_SOCKETS[0][4], $hSocket, $iError) EndIf EndIf EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Client_Stop ; Description ...: Stops the client. ; Syntax.........: _TCP_Client_Stop($hSocket) ; Parameters ....: $hSocket - Client socket. ; Return values .: Success - True ; Failure - False ; Author ........: Kip ; Modified.......: ; Remarks .......: The client socket is the return value of _TCP_Client_Create(). ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Client_Stop($hSocket) Local $iElement, $i $iElement = 0 For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] = $hSocket Then $iElement = $i ExitLoop EndIf Next If $iElement Then ___ASockShutdown($__TCP_SOCKETS[$iElement][0]) TCPCloseSocket($__TCP_SOCKETS[$iElement][0]) ___ArrayDelete($__TCP_SOCKETS, $iElement) Return True EndIf Return False EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_Stop ; Description ...: Stops the server, and closes all client connections. ; Syntax.........: _TCP_Server_Stop() ; Parameters ....: ; Return values .: True ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_Stop() Local $i ___ASockShutdown($__TCP_SOCKETS[0][0]) TCPCloseSocket($__TCP_SOCKETS[0][0]) $__TCP_SOCKETS[0][0] = "" $__TCP_SOCKETS[0][1] = "" $__TCP_SOCKETS[0][2] = "" $__TCP_SOCKETS[0][3] = "" $__TCP_SOCKETS[0][4] = "" $__TCP_SOCKETS[0][5] = "" $__TCP_SOCKETS[0][6] = "" For $i = UBound($__TCP_SOCKETS)-1 to 1 Step -1 ___ArrayDelete($__TCP_SOCKETS, $i) Next Return True EndFunc Func ___TCP_Server_OnSocketEvent( $hWnd, $iMsgID, $WParam, $LParam ) Local $hSocket = $WParam Local $iError = ___HiWord( $LParam ) Local $iEvent = ___LoWord( $LParam ) Local $sDataBuff, $iElement, $i Abs($hWnd) $hSocket = 0 $iElement = 0 For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][1] = $iMsgID Then $hSocket = $__TCP_SOCKETS[$i][0] $iElement = $i ExitLoop EndIf Next If $hSocket Then Switch $iEvent Case $FD_READ $sDataBuff = TCPRecv($hSocket, 1024) Call($__TCP_SOCKETS[0][2], $hSocket, $sDataBuff, $iError) Case $FD_WRITE Call($__TCP_SOCKETS[0][3], $hSocket, $iError) Case $FD_CLOSE ___ASockShutdown($hSocket) TCPCloseSocket($hSocket) Call($__TCP_SOCKETS[0][5], $hSocket, $iError) ___ArrayDelete($__TCP_SOCKETS, $iElement) EndSwitch EndIf EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_DisconnectClient ; Description ...: Disconnects a client of the server. ; Syntax.........: _TCP_Server_DisconnectClient($hSocket) ; Parameters ....: $hSocket - Client socket. ; Return values .: Success - True ; Failure - False ; Author ........: Kip ; Modified.......: ; Remarks .......: The client socket is the $hSocket parameter of a _TCP_RegisterEvent callback function. ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_DisconnectClient($hSocket) Local $iElement, $i $iElement = 0 For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] = $hSocket Then $iElement = $i ExitLoop EndIf Next If $iElement Then ___ASockShutdown($hSocket) TCPCloseSocket($hSocket) ___ArrayDelete($__TCP_SOCKETS, $iElement) Return True EndIf Return False EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_ClientList ; Description ...: Returns the sockets of all connected clients. ; Syntax.........: _TCP_Server_ClientList() ; Parameters ....: ; Return values .: An 1 dimensional array of all connected clients. ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_ClientList() Local $aReturn[1], $i For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] Then ReDim $aReturn[UBound($aReturn)+1] $aReturn[UBound($aReturn)-1] = $__TCP_SOCKETS[$i][0] EndIf Next $aReturn[0] = UBound($aReturn)-1 Return $aReturn EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_Broadcast ; Description ...: Sends data to all connected clients. ; Syntax.........: _TCP_Server_Broadcast($sData) ; Parameters ....: $sData - The data to send. ; Return values .: True ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_Broadcast($sData) Local $i For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] Then TCPSend($__TCP_SOCKETS[$i][0], $sData) Next Return True EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Client_Create ; Description ...: Creates a new client. ; Syntax.........: _TCP_Client_Create($sIP , $iPort) ; Parameters ....: $sIP - The IP address to connect to. ; $iPort - Port on which the created socket will be connected. ; Return values .: Client socket handle. ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Client_Create($sIP , $iPort) ReDim $__TCP_SOCKETS[UBound($__TCP_SOCKETS)+1][7] local $hSocket = ___ASocket() $__TCP_SOCKETS[UBound($__TCP_SOCKETS)-1][0] = $hSocket $__TCP_SOCKETS[UBound($__TCP_SOCKETS)-1][1] = 0x0400 + (UBound($__TCP_SOCKETS)-1) ___ASockSelect( $hSocket, $__TCP_WINDOW, 0x0400 + (UBound($__TCP_SOCKETS)-1), BitOR( $FD_READ, $FD_WRITE, $FD_CONNECT, $FD_CLOSE ) ) GUIRegisterMsg( 0x0400 + (UBound($__TCP_SOCKETS)-1), "___TCP_Client_OnSocketEvent" ) ___ASockConnect( $hSocket, $sIP, $iPort ) Return $hSocket EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_RegisterEvent ; Description ...: Registers an event. ; Syntax.........: _TCP_RegisterEvent($hSocket, $iEvent, $sFunction) ; Parameters ....: $hSocket - Socket of the server or a client. ; $iEvent - Event number. It can be any these values: ; * $TCP_SEND ; * $TCP_RECEIVE ; * $TCP_CONNECT => Client only ; * $TCP_DISCONNECT ; * $TCP_NEWCLIENT => Server only ; Return values .: Success - True ; Failure - False ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_RegisterEvent($hSocket, $iEvent, $sFunction) Local $iSelected = 0 Local $i If $__TCP_SOCKETS[0][0] Then $iSelected = 0 Else For $i = 0 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][0] = $hSocket Then $iSelected = $i ExitLoop EndIf Next If Not $iSelected Then Return 0 EndIf Switch $iEvent Case $TCP_SEND $__TCP_SOCKETS[$iSelected][3] = $sFunction Case $TCP_RECEIVE $__TCP_SOCKETS[$iSelected][2] = $sFunction Case $TCP_CONNECT $__TCP_SOCKETS[$iSelected][4] = $sFunction Case $TCP_DISCONNECT $__TCP_SOCKETS[$iSelected][5] = $sFunction Case $TCP_NEWCLIENT $__TCP_SOCKETS[$iSelected][6] = $sFunction Case Else Return False EndSwitch Return True EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Server_ClientIP ; Description ...: Converts a client socket handle to IP address. ; Syntax.........: _TCP_Server_ClientIP($hSocket) ; Parameters ....: $hSocket - Client socket handle. ; Return values .: A string with the IP address. ; Author ........: Unknown ; Modified.......: Kip ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Server_ClientIP($hSocket) Local $pSocketAddress, $aReturn $pSocketAddress = DllStructCreate("short;ushort;uint;char[8]") $aReturn = DllCall("Ws2_32.dll", "int", "getpeername", "int", $hSocket, "ptr", DllStructGetPtr($pSocketAddress), "int*", DllStructGetSize($pSocketAddress)) If @error Or $aReturn[0] <> 0 Then Return 0 $aReturn = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($pSocketAddress, 3)) If @error Then Return 0 $pSocketAddress = 0 Return $aReturn[0] EndFunc ; #FUNCTION# ;=============================================================================== ; ; Name...........: _TCP_Send ; Description ...: Sends data to a server or client. ; Syntax.........: _TCP_Send($hSocket, $sText) ; Parameters ....: $hSocket - Client or server socket handle. ; $sText - Data to send. ; Return values .: ; Author ........: Kip ; Modified.......: ; Remarks .......: ; Related .......: ; Link ..........; ; Example .......; ; ; ;========================================================================================== Func _TCP_Send($hSocket, $sText) Return TCPSend($hSocket, $sText) EndFunc Func ___TCP_Client_OnSocketEvent( $hWnd, $iMsgID, $WParam, $LParam ) Local $iError = ___HiWord( $LParam ) Local $iEvent = ___LoWord( $LParam ) Local $hSocket, $iElement, $i, $sDataBuff Abs($hWnd) Abs($WParam) $hSocket = 0 $iElement = 0 For $i = 1 to UBound($__TCP_SOCKETS)-1 If $__TCP_SOCKETS[$i][1] = $iMsgID Then $hSocket = $__TCP_SOCKETS[$i][0] $iElement = $i ExitLoop EndIf Next If $hSocket Then Switch $iEvent Case $FD_READ; Data has arrived! $sDataBuff = TCPRecv( $hSocket, 1024) Call($__TCP_SOCKETS[$i][2], $hSocket, $sDataBuff, $iError) $sDataBuff = "" Case $FD_WRITE Call($__TCP_SOCKETS[$i][3], $hSocket, $iError) Case $FD_CONNECT Call($__TCP_SOCKETS[$i][4], $hSocket, $iError) Case $FD_CLOSE ___ASockShutdown( $hSocket ) TCPCloseSocket( $hSocket ) Call($__TCP_SOCKETS[$i][5], $hSocket, $iError) ___ArrayDelete($__TCP_SOCKETS, $iElement) EndSwitch EndIf EndFunc ;================================================================================================================== ; ; Zatorg's Asynchronous Sockets UDF Starts from here. ; ;================================================================================================================== Func ___ASocket($iAddressFamily = 2, $iType = 1, $iProtocol = 6) If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $hSocket = DllCall($hWs2_32, "uint", "socket", "int", $iAddressFamily, "int", $iType, "int", $iProtocol) If @error Then SetError(1, @error) Return -1 EndIf If $hSocket[ 0 ] = -1 Then SetError(2, ___WSAGetLastError()) Return -1 EndIf Return $hSocket[ 0 ] EndFunc ;==>_ASocket Func ___ASockShutdown($hSocket) If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $iRet = DllCall($hWs2_32, "int", "shutdown", "uint", $hSocket, "int", 2) If @error Then SetError(1, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then SetError(2, ___WSAGetLastError()) Return False EndIf Return True EndFunc ;==>_ASockShutdown Func ___ASockClose($hSocket) If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $iRet = DllCall($hWs2_32, "int", "closesocket", "uint", $hSocket) If @error Then SetError(1, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then SetError(2, ___WSAGetLastError()) Return False EndIf Return True EndFunc ;==>_ASockClose Func ___ASockSelect($hSocket, $hWnd, $uiMsg, $iEvent) If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $iRet = DllCall( _ $hWs2_32, _ "int", "WSAAsyncSelect", _ "uint", $hSocket, _ "hwnd", $hWnd, _ "uint", $uiMsg, _ "int", $iEvent _ ) If @error Then SetError(1, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then SetError(2, ___WSAGetLastError()) Return False EndIf Return True EndFunc ;==>_ASockSelect ; Note: you can see that $iMaxPending is set to 5 by default. ; IT DOES NOT MEAN THAT DEFAULT = 5 PENDING CONNECTIONS ; 5 == SOMAXCONN, so don't worry be happy Func ___ASockListen($hSocket, $sIP, $uiPort, $iMaxPending = 5); 5 == SOMAXCONN => No need to change it. Local $iRet Local $stAddress If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) $stAddress = ___SockAddr($sIP, $uiPort) If @error Then SetError(@error, @extended) Return False EndIf $iRet = DllCall($hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($stAddress), "int", DllStructGetSize($stAddress)) If @error Then SetError(3, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then $stAddress = 0; Deallocate SetError(4, ___WSAGetLastError()) Return False EndIf $iRet = DllCall($hWs2_32, "int", "listen", "uint", $hSocket, "int", $iMaxPending) If @error Then SetError(5, @error) Return False EndIf If $iRet[ 0 ] <> 0 Then $stAddress = 0; Deallocate SetError(6, ___WSAGetLastError()) Return False EndIf Return True EndFunc ;==>_ASockListen Func ___ASockConnect($hSocket, $sIP, $uiPort) Local $iRet Local $stAddress If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) $stAddress = ___SockAddr($sIP, $uiPort) If @error Then SetError(@error, @extended) Return False EndIf $iRet = DllCall($hWs2_32, "int", "connect", "uint", $hSocket, "ptr", DllStructGetPtr($stAddress), "int", DllStructGetSize($stAddress)) If @error Then SetError(3, @error) Return False EndIf $iRet = ___WSAGetLastError() If $iRet = 10035 Then; WSAEWOULDBLOCK Return True; Asynchronous connect attempt has been started. EndIf SetExtended(1); Connected immediately Return True EndFunc ;==>_ASockConnect ; A wrapper function to ease all the pain in creating and filling the sockaddr struct Func ___SockAddr($sIP, $iPort, $iAddressFamily = 2) Local $iRet Local $stAddress If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) $stAddress = DllStructCreate("short; ushort; uint; char[8]") If @error Then SetError(1, @error) Return False EndIf DllStructSetData($stAddress, 1, $iAddressFamily) $iRet = DllCall($hWs2_32, "ushort", "htons", "ushort", $iPort) DllStructSetData($stAddress, 2, $iRet[ 0 ]) $iRet = DllCall($hWs2_32, "uint", "inet_addr", "str", $sIP) If $iRet[ 0 ] = 0xffffffff Then; INADDR_NONE $stAddress = 0; Deallocate SetError(2, ___WSAGetLastError()) Return False EndIf DllStructSetData($stAddress, 3, $iRet[ 0 ]) Return $stAddress EndFunc ;==>__SockAddr Func ___WSAGetLastError() If $hWs2_32 = -1 Then $hWs2_32 = DllOpen( "Ws2_32.dll" ) Local $iRet = DllCall($hWs2_32, "int", "WSAGetLastError") If @error Then ;ConsoleWrite("+> _WSAGetLastError(): WSAGetLastError() failed. Script line number: " & @ScriptLineNumber & @CRLF) SetExtended(1) Return 0 EndIf Return $iRet[ 0 ] EndFunc ;==>_WSAGetLastError ; Got these here: ; http://www.autoitscript.com/forum/index.php?showtopic=5620&hl=MAKELONG Func ___MakeLong($LoWord, $HiWord) Return BitOR($HiWord * 0x10000, BitAND($LoWord, 0xFFFF)); Thanks Larry EndFunc ;==>_MakeLong Func ___HiWord($Long) Return BitShift($Long, 16); Thanks Valik EndFunc ;==>_HiWord Func ___LoWord($Long) Return BitAND($Long, 0xFFFF); Thanks Valik EndFunc ;==>_LoWord ; ========================================= Array functions ; #FUNCTION# ==================================================================================================================== ; Name...........: _ArrayDelete ; Description ...: Deletes the specified element from the given array. ; Syntax.........: _ArrayDelete(ByRef $avArray, $iElement) ; Parameters ....: $avArray - Array to modify ; $iElement - Element to delete ; Return values .: Success - New size of the array ; Failure - 0, sets @error to: ; |1 - $avArray is not an array ; |3 - $avArray has too many dimensions (only up to 2D supported) ; |(2 - Deprecated error code) ; Author ........: Cephas <cephas at clergy dot net> ; Modified.......: Jos van der Zande <jdeb at autoitscript dot com> - array passed ByRef, Ultima - 2D arrays supported, reworked function (no longer needs temporary array; faster when deleting from end) ; Remarks .......: If the array has one element left (or one row for 2D arrays), it will be set to "" after _ArrayDelete() is used on it. ; Related .......: _ArrayAdd, _ArrayInsert, _ArrayPop, _ArrayPush ; Link ..........; ; Example .......; Yes ; =============================================================================================================================== Func ___ArrayDelete(ByRef $avArray, $iElement) If Not IsArray($avArray) Then Return SetError(1, 0, 0) Local $iUBound = UBound($avArray, 1) - 1 If Not $iUBound Then $avArray = "" Return 0 EndIf ; Bounds checking If $iElement < 0 Then $iElement = 0 If $iElement > $iUBound Then $iElement = $iUBound ; Move items after $iElement up by 1 Switch UBound($avArray, 0) Case 1 For $i = $iElement To $iUBound - 1 $avArray[$i] = $avArray[$i + 1] Next ReDim $avArray[$iUBound] Case 2 Local $iSubMax = UBound($avArray, 2) - 1 For $i = $iElement To $iUBound - 1 For $j = 0 To $iSubMax $avArray[$i][$j] = $avArray[$i + 1][$j] Next Next ReDim $avArray[$iUBound][$iSubMax + 1] Case Else Return SetError(3, 0, 0) EndSwitch Return $iUBound EndFunc ;==>_ArrayDelete mysql.au3 Edited August 24, 2011 by johnnyd Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now