matwachich

[UDF] Simple & flexible multi-clients TCP server

1 post in this topic

#1 ·  Posted (edited)

Here I am again, with a brand new UDF! (not so new through...)

Taking (great) advantage of the new maps feature, I made a simple, flexible multi-clients TCP server UDF.

Features:

  • You can create multiples servers in one script
  • Peers limit is optional (the real peers limit is your RAM and the maps performances)
  • You can configure max data receive len (2nd argument of TCPRecv) on a per-client basis
  • You can set an optional idle time-out (time without receiving any data before peer gets disconnected)
  • Each peer has an empty Map that can contain user defined data
  • You can set a function that will be called for each connected peer at pre-defined interval (onPeerCycle callback)
  • The UDF is callback driven (onConnect, onDisconnect, onReceive, onError, onPeerCycle)
  • You can set a disconnect message when kicking a peer. This message will be passed to the onDisconnect callback
  • onReceive callback must return the number of bytes that have been consumed. Say you receive 100 bytes of data but you used (consumed) only 70 bytes, by returning 70 from the callback the remaining 30 bytes will be buffered and passed again on the next call to onReceive

Known bugs:

  • TCPRecv bug! the function doesn't detect peer disconnection (hope this will be fixed soon)

Download:

https://github.com/matwachich/generic-tcp-server/

 

Thanks in advance for your feedback!

Edited by matwachich
1 person likes this

Share this post


Link to post
Share on other sites



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 account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • AlexFing17
      By AlexFing17
      i am trying to figure out how a server can connect to a client Over the internet. 
      In this is script. The client connects to the server on the same machine (localhost) and executes the commands from the client.
      How can I change that instead communicating over localhost to communicate over the internet with tcp ipaddress and a port.
       
      What i actually need help of is
      1. The server will open a port and  listen to communication from a No-ip address
      2. I input the no-ip address and correct port in the client side, and when i click on connect, it connects to the server if its online
       
       
      This is the client
      #include <GuiConstantsEx.au3> THIS IS THE CLIENT #include <NamedPipes.au3> #include <StaticConstants.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> ; =============================================================================================================================== ; Description ...: This is the client side of the pipe demo ; Author ........: Paul Campbell (PaulIA) ; Notes .........: ; =============================================================================================================================== ; =============================================================================================================================== ; Global constants ; =============================================================================================================================== Global Const $BUFSIZE = 4096 Global Const $DEFCMD = "cmd.exe /c dir c:\" Global Const $PIPE_NAME = "\\$\\pipe\\AutoIt3" Global Const $ERROR_MORE_DATA = 234 ; =============================================================================================================================== ; Global variables ; =============================================================================================================================== Global $g_idEdit, $g_idMemo, $g_idSend, $g_idServer, $g_hPipe ; =============================================================================================================================== ; Main ; =============================================================================================================================== CreateGUI() MsgLoop() ; =============================================================================================================================== ; Creates a GUI for the client ; =============================================================================================================================== Func CreateGUI() Local $hGUI = GUICreate("FarC0nn3c7", 500, 400, -1, -1, $WS_SIZEBOX) GUICtrlCreateLabel("Server:", 2, 14, 52, 20, $SS_RIGHT) $g_idServer = GUICtrlCreateEdit("<local>", 56, 10, 200, 20, $SS_LEFT) GUICtrlCreateLabel("Command:", 2, 36, 52, 20, $SS_RIGHT) $g_idEdit = GUICtrlCreateEdit($DEFCMD, 56, 32, 370, 20, $SS_LEFT) $g_idSend = GUICtrlCreateButton("Pawn Dem", 430, 32, 60, 20) $g_idMemo = GUICtrlCreateEdit("", 0, 62, _WinAPI_GetClientWidth($hGUI), 332) GUICtrlSetFont($g_idMemo, 9, 400, 0, "Courier New") GUISetState() EndFunc ;==>CreateGUI ; =============================================================================================================================== ; Logs an error message to the display ; =============================================================================================================================== Func LogError($sMessage) $sMessage &= " (" & _WinAPI_GetLastErrorMessage() & ")" GUICtrlSetData($g_idMemo, GUICtrlRead($g_idMemo) & $sMessage & @CRLF) EndFunc ;==>LogError ; =============================================================================================================================== ; Logs a message to the display ; =============================================================================================================================== Func LogMsg($sMessage) GUICtrlSetData($g_idMemo, GUICtrlRead($g_idMemo) & $sMessage & @CRLF) EndFunc ;==>LogMsg ; =============================================================================================================================== ; MsgLoop ; =============================================================================================================================== Func MsgLoop() While True Switch GUIGetMsg() Case $g_idSend SendCmd() Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd EndFunc ;==>MsgLoop ; =============================================================================================================================== ; This function opens a pipe to the server ; =============================================================================================================================== Func OpenPipe() Local $sName, $sPipe ; Get pipe handle $sName = GUICtrlRead($g_idServer) If $sName = "<local>" Then $sName = "." $sPipe = StringReplace($PIPE_NAME, "$", $sName) $g_hPipe = _WinAPI_CreateFile($sPipe, 2, 6) If $g_hPipe <> -1 Then Return True LogError("OpenPipe failed") Return False EndFunc ;==>OpenPipe ; =============================================================================================================================== ; This function reads a message from the pipe ; =============================================================================================================================== Func ReadMsg() Local $bSuccess, $iRead, $pBuffer, $tBuffer $tBuffer = DllStructCreate("char Text[4096]") $pBuffer = DllStructGetPtr($tBuffer) GUICtrlSetData($g_idMemo, "") While 1 $bSuccess = _WinAPI_ReadFile($g_hPipe, $pBuffer, $BUFSIZE, $iRead, 0) If $iRead = 0 Then ExitLoop If Not $bSuccess Or (_WinAPI_GetLastError() = $ERROR_MORE_DATA) Then ExitLoop GUICtrlSetData($g_idMemo, StringLeft(DllStructGetData($tBuffer, "Text"), $iRead), 1) WEnd EndFunc ;==>ReadMsg ; =============================================================================================================================== ; This function sends a command to the server ; =============================================================================================================================== Func SendCmd() If OpenPipe() Then SetReadMode() WriteMsg(GUICtrlRead($g_idEdit)) ReadMsg() _WinAPI_CloseHandle($g_hPipe) EndIf EndFunc ;==>SendCmd ; =============================================================================================================================== ; This function sets the pipe read mode ; =============================================================================================================================== Func SetReadMode() If Not _NamedPipes_SetNamedPipeHandleState($g_hPipe, 1, 0, 0, 0) Then LogError("SetReadMode: _NamedPipes_SetNamedPipeHandleState failed") EndIf EndFunc ;==>SetReadMode ; =============================================================================================================================== ; This function writes a message to the pipe ; =============================================================================================================================== Func WriteMsg($sMessage) Local $iWritten, $iBuffer, $pBuffer, $tBuffer $iBuffer = StringLen($sMessage) + 1 $tBuffer = DllStructCreate("char Text[" & $iBuffer & "]") $pBuffer = DllStructGetPtr($tBuffer) DllStructSetData($tBuffer, "Text", $sMessage) If Not _WinAPI_WriteFile($g_hPipe, $pBuffer, $iBuffer, $iWritten, 0) Then LogError("WriteMsg: _WinAPI_WriteFile failed") EndIf EndFunc ;==>WriteMsg  
      And this is the server
      #include <GuiConstantsEx.au3> #include <NamedPipes.au3> #include <WinAPI.au3> #include <WindowsConstants.au3> #NoTrayIcon ; =============================================================================================================================== ; Description ...: This is the server side of the pipe demo ; Author ........: Paul Campbell (PaulIA) ; Notes .........: ; =============================================================================================================================== ; =============================================================================================================================== ; Global constants ; =============================================================================================================================== Global Const $DEBUGGING = False Global Const $BUFSIZE = 4096 Global Const $PIPE_NAME = "\\.\\pipe\\AutoIt3" Global Const $TIMEOUT = 5000 Global Const $WAIT_TIMEOUT = 258 Global Const $ERROR_IO_PENDING = 997 Global Const $ERROR_PIPE_CONNECTED = 535 ; =============================================================================================================================== ; Global variables ; =============================================================================================================================== Global $g_hEvent, $g_idMemo, $g_pOverlap, $g_tOverlap, $g_hPipe, $g_hReadPipe, $g_iState, $g_iToWrite ; =============================================================================================================================== ; Main ; =============================================================================================================================== CreateGUI() InitPipe() MsgLoop() ; =============================================================================================================================== ; Creates a GUI for the server ; =============================================================================================================================== Func CreateGUI() Local $hGUI $hGUI = GUICreate("Pipe Server", 500, 400, -1, -1, $WS_SIZEBOX) $g_idMemo = GUICtrlCreateEdit("", 0, 0, _WinAPI_GetClientWidth($hGUI), _WinAPI_GetClientHeight($hGUI)) GUICtrlSetFont($g_idMemo, 9, 400, 0, "Courier New") GUISetState() EndFunc ;==>CreateGUI ; =============================================================================================================================== ; This function creates an instance of a named pipe ; =============================================================================================================================== Func InitPipe() ; Create an event object for the instance $g_tOverlap = DllStructCreate($tagOVERLAPPED) $g_pOverlap = DllStructGetPtr($g_tOverlap) $g_hEvent = _WinAPI_CreateEvent() If $g_hEvent = 0 Then LogError("InitPipe ..........: API_CreateEvent failed") Return EndIf DllStructSetData($g_tOverlap, "hEvent", $g_hEvent) ; Create a named pipe $g_hPipe = _NamedPipes_CreateNamedPipe($PIPE_NAME, _ ; Pipe name 2, _ ; The pipe is bi-directional 2, _ ; Overlapped mode is enabled 0, _ ; No security ACL flags 1, _ ; Data is written to the pipe as a stream of messages 1, _ ; Data is read from the pipe as a stream of messages 0, _ ; Blocking mode is enabled 1, _ ; Maximum number of instances $BUFSIZE, _ ; Output buffer size $BUFSIZE, _ ; Input buffer size $TIMEOUT, _ ; Client time out 0) ; Default security attributes If $g_hPipe = -1 Then LogError("InitPipe ..........: _NamedPipes_CreateNamedPipe failed") Else ; Connect pipe instance to client ConnectClient() EndIf EndFunc ;==>InitPipe ; =============================================================================================================================== ; This function loops waiting for a connection event or the GUI to close ; =============================================================================================================================== Func MsgLoop() Local $iEvent Do $iEvent = _WinAPI_WaitForSingleObject($g_hEvent, 0) If $iEvent < 0 Then LogError("MsgLoop ...........: _WinAPI_WaitForSingleObject failed") Exit EndIf If $iEvent = $WAIT_TIMEOUT Then ContinueLoop Debug("MsgLoop ...........: Instance signaled") Switch $g_iState Case 0 CheckConnect() Case 1 ReadRequest() Case 2 CheckPending() Case 3 RelayOutput() EndSwitch Until GUIGetMsg() = $GUI_EVENT_CLOSE EndFunc ;==>MsgLoop ; =============================================================================================================================== ; Checks to see if the pending client connection has finished ; =============================================================================================================================== Func CheckConnect() Local $iBytes ; Was the operation successful? If Not _WinAPI_GetOverlappedResult($g_hPipe, $g_pOverlap, $iBytes, False) Then LogError("CheckConnect ......: Connection failed") ReconnectClient() Else $g_iState = 1 EndIf EndFunc ;==>CheckConnect ; =============================================================================================================================== ; This function reads a request message from the client ; =============================================================================================================================== Func ReadRequest() Local $pBuffer, $tBuffer, $iRead, $bSuccess $tBuffer = DllStructCreate("char Text[" & $BUFSIZE & "]") $pBuffer = DllStructGetPtr($tBuffer) $bSuccess = _WinAPI_ReadFile($g_hPipe, $pBuffer, $BUFSIZE, $iRead, $g_pOverlap) If $bSuccess And ($iRead <> 0) Then ; The read operation completed successfully Debug("ReadRequest .......: Read success") Else ; Wait for read Buffer to complete If Not _WinAPI_GetOverlappedResult($g_hPipe, $g_pOverlap, $iRead, True) Then LogError("ReadRequest .......: _WinAPI_GetOverlappedResult failed") ReconnectClient() Return Else ; Read the command from the pipe $bSuccess = _WinAPI_ReadFile($g_hPipe, $pBuffer, $BUFSIZE, $iRead, $g_pOverlap) If Not $bSuccess Or ($iRead = 0) Then LogError("ReadRequest .......: _WinAPI_ReadFile failed") ReconnectClient() Return EndIf EndIf EndIf ; Execute the console command If Not ExecuteCmd(DllStructGetData($tBuffer, "Text")) Then ReconnectClient() Return EndIf ; Relay console output back to the client $g_iState = 3 EndFunc ;==>ReadRequest ; =============================================================================================================================== ; This function relays the console output back to the client ; =============================================================================================================================== Func CheckPending() Local $bSuccess, $iWritten $bSuccess = _WinAPI_GetOverlappedResult($g_hPipe, $g_pOverlap, $iWritten, False) If Not $bSuccess Or ($iWritten <> $g_iToWrite) Then Debug("CheckPending ......: Write reconnecting") ReconnectClient() Else Debug("CheckPending ......: Write complete") $g_iState = 3 EndIf EndFunc ;==>CheckPending ; =============================================================================================================================== ; This function relays the console output back to the client ; =============================================================================================================================== Func RelayOutput() Local $pBuffer, $tBuffer, $sLine, $iRead, $bSuccess, $iWritten $tBuffer = DllStructCreate("char Text[" & $BUFSIZE & "]") $pBuffer = DllStructGetPtr($tBuffer) ; Read data from console pipe _WinAPI_ReadFile($g_hReadPipe, $pBuffer, $BUFSIZE, $iRead) If $iRead = 0 Then LogMsg("RelayOutput .......: Write done") _WinAPI_CloseHandle($g_hReadPipe) _WinAPI_FlushFileBuffers($g_hPipe) ReconnectClient() Return EndIf ; Get the data and strip out the extra carriage returns $sLine = StringLeft(DllStructGetData($tBuffer, "Text"), $iRead) $sLine = StringReplace($sLine, @CR & @CR, @CR) $g_iToWrite = StringLen($sLine) DllStructSetData($tBuffer, "Text", $sLine) ; Relay the data back to the client $bSuccess = _WinAPI_WriteFile($g_hPipe, $pBuffer, $g_iToWrite, $iWritten, $g_pOverlap) If $bSuccess And ($iWritten = $g_iToWrite) Then Debug("RelayOutput .......: Write success") Else If Not $bSuccess And (_WinAPI_GetLastError() = $ERROR_IO_PENDING) Then Debug("RelayOutput .......: Write pending") $g_iState = 2 Else ; An error occurred, disconnect from the client LogError("RelayOutput .......: Write failed") ReconnectClient() EndIf EndIf EndFunc ;==>RelayOutput ; =============================================================================================================================== ; This function is called to start an overlapped connection operation ; =============================================================================================================================== Func ConnectClient() $g_iState = 0 ; Start an overlapped connection If _NamedPipes_ConnectNamedPipe($g_hPipe, $g_pOverlap) Then LogError("ConnectClient .....: ConnectNamedPipe 1 failed") Else Switch @error ; The overlapped connection is in progress Case $ERROR_IO_PENDING Debug("ConnectClient .....: Pending") ; Client is already connected, so signal an event Case $ERROR_PIPE_CONNECTED LogMsg("ConnectClient .....: Connected") $g_iState = 1 If Not _WinAPI_SetEvent(DllStructGetData($g_tOverlap, "hEvent")) Then LogError("ConnectClient .....: SetEvent failed") EndIf ; Error occurred during the connection event Case Else LogError("ConnectClient .....: ConnectNamedPipe 2 failed") EndSwitch EndIf EndFunc ;==>ConnectClient ; =============================================================================================================================== ; Dumps debug information to the screen ; =============================================================================================================================== Func Debug($sMessage) If $DEBUGGING Then LogMsg($sMessage) EndFunc ;==>Debug ; =============================================================================================================================== ; Executes a command and returns the results ; =============================================================================================================================== Func ExecuteCmd($sCmd) Local $tProcess, $tSecurity, $tStartup, $hWritePipe ; Set up security attributes $tSecurity = DllStructCreate($tagSECURITY_ATTRIBUTES) DllStructSetData($tSecurity, "Length", DllStructGetSize($tSecurity)) DllStructSetData($tSecurity, "InheritHandle", True) ; Create a pipe for the child process's STDOUT If Not _NamedPipes_CreatePipe($g_hReadPipe, $hWritePipe, $tSecurity) Then LogError("ExecuteCmd ........: _NamedPipes_CreatePipe failed") Return False EndIf ; Create child process $tProcess = DllStructCreate($tagPROCESS_INFORMATION) $tStartup = DllStructCreate($tagSTARTUPINFO) DllStructSetData($tStartup, "Size", DllStructGetSize($tStartup)) DllStructSetData($tStartup, "Flags", BitOR($STARTF_USESTDHANDLES, $STARTF_USESHOWWINDOW)) DllStructSetData($tStartup, "StdOutput", $hWritePipe) DllStructSetData($tStartup, "StdError", $hWritePipe) If Not _WinAPI_CreateProcess("", $sCmd, 0, 0, True, 0, 0, "", DllStructGetPtr($tStartup), DllStructGetPtr($tProcess)) Then LogError("ExecuteCmd ........: _WinAPI_CreateProcess failed") _WinAPI_CloseHandle($g_hReadPipe) _WinAPI_CloseHandle($hWritePipe) Return False EndIf _WinAPI_CloseHandle(DllStructGetData($tProcess, "hProcess")) _WinAPI_CloseHandle(DllStructGetData($tProcess, "hThread")) ; Close the write end of the pipe so that we can read from the read end _WinAPI_CloseHandle($hWritePipe) LogMsg("ExecuteCommand ....: " & $sCmd) Return True EndFunc ;==>ExecuteCmd ; =============================================================================================================================== ; Logs an error message to the display ; =============================================================================================================================== Func LogError($sMessage) $sMessage &= " (" & _WinAPI_GetLastErrorMessage() & ")" ConsoleWrite($sMessage & @LF) EndFunc ;==>LogError ; =============================================================================================================================== ; This function is called when an error occurs or when the client closes its handle to the pipe ; =============================================================================================================================== Func ReconnectClient() ; Disconnect the pipe instance If Not _NamedPipes_DisconnectNamedPipe($g_hPipe) Then LogError("ReconnectClient ...: DisonnectNamedPipe failed") Return EndIf ; Connect to a new client ConnectClient() EndFunc ;==>ReconnectClient  
    • Jefrey
      By Jefrey
      I've ported these two functions from PHP to AU3 to work with URLs.
      Made them for those who work with libraries like HTTP.au3 (not the one I coded), that needs passing the server domain, path, etc., instead of the full URL.
      Grab the lib here.
      ParseURL( $sURL )
      Parses the URL and splits it into defined parts. Returns an array:
      [0] = Full URL (same as $sURL) [1] = Protocol (i.e.: http, https, ftp, ws...) [2] = Domain [3] = Port (or null if not specified) [4] = Path (or null if not specified) [5] = Query string (everything after the ? - or null if not specified) Example:
      $aExample = ParseURL("https://google.com:8080/?name=doe") MsgBox(0, "Test", "URL: " & $aExample[0] & @CRLF & _ "Protocol: " & $aExample[1] & @CRLF & _ "Domain: " & $aExample[2] & @CRLF & _ "Port: " & $aExample[3] & @CRLF & _ "Path: " & $aExample[4] & @CRLF & _ "Query string: " & $aExample[5])  
      ParseStr( $sStr )
      Parses a query string (similar to the [5] of the previous function) and returns a multidimensional array, where:
      [0][0] = number of variables found [0][1] = ununsed [1][0] = key name of the first variable [1][1] = first variable value (already URL decoded) [n][0] = key name of the nth variable [n][1] = nth variable value (already URL decoded) Example:
      include <Array.au3> ; need only to do _ArrayDisplay, not needed by the lib _ArrayDisplay(ParseStr("foo=bar&test=lol%20123")) #cs Result is: [0][0] = 2 [0][1] = ununsed [1][0] = foo [1][1] = bar [2][0] = test [2][1] = lol 123 #ce Feel free to fork!
    • razor999
      By razor999
      please help me,
      my script not working, i want gui run like local real time
      #NoTrayIcon #include <INet.au3> #include <String.au3> #include <array.au3> Local $Refresh = 0 ; Set refresh OFF Local $Timer = TimerInit() Local $RefreshEvery = 1 ; seconds ;Global $nCheck Global $link = BinaryToString (InetRead ("http://test.no-ip.info/time.asp")) Global $timeserver = _StringBetween($link, 'id="timeserver">' , '</span>') Global $realtime = $timeserver[0] GuiCreate("Time My Server",200,50) $htime = GuiCtrlCreateLabel("", 10, 10, 180, 20) $btnStart = GUICtrlCreateButton("Start", 40, 30, 57, 17) $btnStop = GUICtrlCreateButton("Stop", 110, 30, 57, 17) GuiSetState() While 1 $nMsg = GUIGetMsg() Select Case $nMsg = $btnStart $Refresh = 1 ; Set refresh ON Case $nMsg = $btnStop $Refresh = 0 ; Set refresh OFF EndSelect If $Refresh And (TimerDiff($Timer) > $RefreshEvery*1000) Then time() $Timer = TimerInit() EndIf WEnd Func time() ;If @SEC <> $nCheck Then GUICtrlSetData($htime, "The current time is " & $realtime) ;$nCheck = @SEC ;EndIf EndFunc  
       
    • DrAhmed
      By DrAhmed
      I am working on a code of  Client-Server Connection for a while (Like Teamviewer) , the problem is that the server keeps disconnecting and connecting all the time , In the client i wrote a code to notify me each time server is online , I am getting around 10 notifications each 1 minute from same server :
      This is the server code :
      TCPStartup() Local $ConnectedSocket Local $My_IP = "127.0.0.1" Local $My_PORT = '5000' Local $UserID = "MyID" ; Connect Connect($My_IP, $My_PORT) While 1 If TCPConnect($My_IP, $My_PORT) <> -1 Then $recv = TCPRecv($ConnectedSocket, 2048) $RecvSpl = StringSplit($recv, "|") Switch $RecvSpl[1] Case "order1" ; Do something MsgBox(64,"Success","You are now connected to the client") AddLogToClinet("My server is Online", $UserID, "Green") EndSwitch Else $Connected = False Connect($IP, $My_PORT) EndIf Sleep(100) WEnd ; Connect To the Client Func Connect($IP, $Port) Local $iConnectAttempts = 0 TCPStartup() Do $ConnectedSocket = TCPConnect($IP, $Port) Sleep(1000) Until ($ConnectedSocket > 0 or $iConnectAttempts > 10) Return SetError(@error, 0, $ConnectedSocket) EndFunc ;==>Connect ; Send To Client Func SockSend($Cmd, $Text) TCPSend($ConnectedSocket, $Cmd & $SockSpl & $Text & $PocketSpl, 4) EndFunc ;==>SockSend ; Add Log To Server Func AddLogToClinet($Data, $UserID, $Color) SockSend("AddLog", $Data & $SockSpl & $UserID & $SockSpl & $Color) EndFunc ;==>AddLogToClinet At first the Connection function was : 
      ; Connect To the Client ( Old ) Func Connect($IP, $Port) TCPStartup() $ConnectedSocket = TCPConnect($IP, $Port) If @error Then Connect($IP, $My_PORT) ; <<<<<<<<<<<<<<< This was the causing recursion error Else $Connected = True EndIf EndFunc ;==>Connect It was working  good , except I had 'recursion level has been exceeded  error (old one)

       I've tried  increasing the delay for current code by :
      Opt("TCPTimeout", 5000) However it did not help yet what do you suggest to me ?
       
    • Andreik
      By Andreik
      I am working on a desktop remote application so I made a simple server and client to send binary screen captures from client to server. All it's good if I test both scripts on my computer but when the client is in other network many screen shots are corrupted and some of them looks good. Have any idea why?
       
      Client:
      #include <ScreenCapture.au3> #include <Memory.au3> #include <WinAPI.au3> #include <GDIPlus.au3> TCPStartup() $Client = TCPConnect(@IPAddress1,12100) _GDIPlus_Startup() While True Local $hHBitmap = _ScreenCapture_Capture('') Local $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap) $bData = _GDIPlus_StreamImage2BinaryString($hBitmap) _GDIPlus_BitmapDispose($hBitmap) _WinAPI_DeleteObject($hHBitmap) TCPSend($Client,'~stream:' & BinaryLen($bData)) While BinaryLen($bData) $a = TCPSend($Client, $bData) $bData = BinaryMid($bData, $a+1, BinaryLen($bData)-$a) WEnd Sleep(10) WEnd TCPCloseSocket($Client) TCPShutdown() _GDIPlus_Shutdown() Func _GDIPlus_StreamImage2BinaryString($hBitmap, $sFormat = "JPG", $iQuality = 100) ;UEZ Local $sImgCLSID, $tGUID, $tParams, $tData Switch $sFormat Case "JPG" $sImgCLSID = _GDIPlus_EncodersGetCLSID($sFormat) $tGUID = _WinAPI_GUIDFromString($sImgCLSID) $tData = DllStructCreate("int Quality") DllStructSetData($tData, "Quality", $iQuality) ;quality 0-100 Local $pData = DllStructGetPtr($tData) $tParams = _GDIPlus_ParamInit(1) _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData) Case "PNG", "BMP", "GIF", "TIF" $sImgCLSID = _GDIPlus_EncodersGetCLSID($sFormat) $tGUID = _WinAPI_GUIDFromString($sImgCLSID) Case Else Return SetError(1, 0, 0) EndSwitch Local $hStream = _WinAPI_CreateStreamOnHGlobal() ;http://msdn.microsoft.com/en-us/library/ms864401.aspx If @error Then Return SetError(2, 0, 0) _GDIPlus_ImageSaveToStream($hBitmap, $hStream, DllStructGetPtr($tGUID), DllStructGetPtr($tParams)) If @error Then Return SetError(3, 0, 0) Local $hMemory = _WinAPI_GetHGlobalFromStream($hStream) ;http://msdn.microsoft.com/en-us/library/aa911736.aspx If @error Then Return SetError(4, 0, 0) Local $iMemSize = _MemGlobalSize($hMemory) If Not $iMemSize Then Return SetError(5, 0, 0) Local $pMem = _MemGlobalLock($hMemory) $tData = DllStructCreate("byte[" & $iMemSize & "]", $pMem) Local $bData = DllStructGetData($tData, 1) _WinAPI_ReleaseStream($hStream) ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms221473(v=vs.85).aspx _MemGlobalFree($hMemory) Return $bData EndFunc ;==>_GDIPlus_StreamImage2BinaryString  
      Server
      Global $Buffer, $BufferSize Global $Count = 0 TCPStartup() $Server = TCPListen(@IPAddress1,12100) If @error Then MsgBox(0,'',@error) Do $Socket = TCPAccept($Server) Sleep(10) Until $Socket <> -1 While True $Recv = TCPRecv($Socket,10240) If $Recv = -1 Then ExitLoop ElseIf $Recv Then If StringLeft($Recv,7) = '~stream' Then $BufferSize = StringSplit($Recv,':')[2] $Buffer = '0x' Do $Recv = TCPRecv($Socket,10240) If BinaryLen($Recv) <> 0 Then $BufferSize -= BinaryLen($Recv) $Buffer &= StringTrimLeft($Recv,2) EndIf Until $BufferSize = 0 $hFile = FileOpen(@ScriptDir & '\Screen' & $Count & '.jpeg',18) FileWrite($hFile,$Buffer) FileClose($hFile) $Buffer = Null $Count += 1 EndIf If $Count = 100 Then ExitLoop EndIf Sleep(10) WEnd TCPCloseSocket($Socket) TCPCloseSocket($Server) TCPShutdown() Exit