Jump to content
funkey

Another TCP server (written with my socket_UDF)

Recommended Posts

funkey

Hello, I just made another TCP server. I will use the server for data collection and a lot of clients can get the data from TCP. I now use it for UDP broadcast some devices to get their IP's. You can also use it for chat's.

It is very low level, but so you have more options than with the pure AutoIt functions.

Just start the server in SciTE to see the console outputs. Then you can start up to 63 clients to talk to the server.

I hope you like it.

Server script:

#include "socket_UDF.au3"
;funkey 2013.06.21

_WSAStartup()

Global $iSocket
Global $iReturn
Global $iPort = 20500
Global $sIP_Connected
Global $iPort_Connected
Global $tBuffer = DllStructCreate("char buffer[512]")


$iSocket = _socket($AF_INET, $SOCK_STREAM, $IPPROTO_TCP)
ConsoleWrite("Listen Socket: " & $iSocket & @CRLF)

Global $tReUse = DllStructCreate("BOOLEAN reuse")
DllStructSetData($tReUse, "reuse", True) ; enable reusing the same port
$iReturn = _setsockopt($iSocket, $SOL_SOCKET, $SO_REUSEADDR, $tReUse) ; set reusing option for the port
If $iReturn Then
ConsoleWrite("SetSockOpt error setting reusing the same port!. Windows Sockets Error Codes: " & _WSAGetLastError() & @CRLF)
EndIf

$iReturn = _bind($iSocket, @IPAddress1, $iPort) ;local IP-Address and port to use
If $iReturn Then
ConsoleWrite("Bind error: " & $iReturn & @CRLF) ; 0 is OK
EndIf

$iReturn = _listen($iSocket, 1)
If $iReturn Then
ConsoleWrite("Listen error: " & $iReturn & @CRLF) ; 0 is OK
EndIf

Global $iNewSocket
Global $tReadFds = DllStructCreate($tagFd_set)
Global $tReadFds_Copy = DllStructCreate($tagFd_set)
_FD_ZERO($tReadFds)
_FD_SET($iSocket, $tReadFds)
Global $iSocketMax = $iSocket
Global $iSocketNow
Global $sDataRcv

While 1

DllCall('ntdll.dll', 'none', 'RtlMoveMemory', 'struct*', $tReadFds_Copy, 'struct*', $tReadFds, 'ULONG_PTR', DllStructGetSize($tReadFds))

$iReturn = _select($iSocketMax + 1, $tReadFds_Copy, 2000) ;timeout 2 seconds
If _FD_ISSET($iSocket, $tReadFds_Copy) Then
$iNewSocket = _accept($iSocket, $sIP_Connected, $iPort_Connected)
_FD_SET($iNewSocket, $tReadFds)
_FD_SHOW($tReadFds)
If $iNewSocket > $iSocketMax Then $iSocketMax = $iNewSocket
ConsoleWrite("New connected socket: " & $iNewSocket & @TAB & "IP: " & $sIP_Connected & @TAB & "Port: " & $iPort_Connected & @LF)
EndIf

For $i = 2 To DllStructGetData($tReadFds, "fd_count")
$iSocketNow = DllStructGetData($tReadFds, "fd_array", $i)
If _FD_ISSET($iSocketNow, $tReadFds_Copy) Then
DllCall('ntdll.dll', 'none', 'RtlZeroMemory', 'struct*', $tBuffer, 'ULONG_PTR', DllStructGetSize($tBuffer))
If _recv($iSocketNow, $tBuffer) = $SOCKET_ERROR Then
_closesocket($iSocketNow)
_FD_CLR($iSocketNow, $tReadFds)
Else
$sDataRcv = DllStructGetData($tBuffer, 1)
ConsoleWrite("Data received: " & $sDataRcv & @LF)
If $sDataRcv == "CloseServer!" Then
ExitLoop 2
EndIf
EndIf
EndIf
Next

WEnd

For $i = 1 To DllStructGetData($tReadFds, "fd_count")
_closesocket(DllStructGetData($tReadFds, "fd_array", $i))
Next

_WSACleanup()


Func _FD_SHOW(ByRef $tFd_set)
For $i = 1 To DllStructGetData($tFd_set, "fd_count")
ConsoleWrite($i & ":" & @TAB & DllStructGetData($tFd_set, "fd_array", $i) & @LF)
Next
EndFunc ;==>_FD_SHOW

socket_UDF and example.rar

  • Like 3

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Chimp

Hi funkey

nice,

thanks for sharing

....  I now use it for UDP broadcast some devices to get their IP's. ....

 

could you please post an example to achieve this?

thanks


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites
funkey

 

Hi funkey

 

nice,

thanks for sharing

 

 

could you please post an example to achieve this?

 

thanks

This depends on devices you have and is different for every kind.

I have scripts to list all 'Siemens Sentron devices' and another one to list all 'Moxa Serial Device Servers' in our network.


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Chimp

so, there are specific broadcast for different devices?
isn't it there a general purpose broadcast?
I do not knows how that works.


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites
funkey

For example I send a few characters via UDP broadcast on a specified port (that's why I build that UDF - AutoIt does not support this, or this is buggy) to my network. Only devices that wait for information on that port and that know the characters send the requested information back.

But what information do you want to get from what devices?


Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Chimp

I do not know if it's possible, but i wonder if an unknown device that responds to a ping, can be asked to respond what type of device is himself, for example if it's a router or a network printer or something else?
or maybe is possible the opposite of this?.So that I can broadcast for specific devices types (network printers for example?) and get response from (all) that type of devices only?

Edited by PincoPanco

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites
funkey

If think, that is not possible for all devices, but for some devices you could get the MAC address from IP address and then look what company made the device (for example use http://wintelguy.com/index.pl to find this out). Here is a script to receive the MAC address via ARP request:

#include "socket_UDF.au3"

_WSAStartup()

Global $MAC = _SendARP(@IPAddress1)
ConsoleWrite("Local MAC address: " & $MAC & @LF)
Global $MAC = _SendARP("192.168.3.4")
ConsoleWrite("Remote MAC address: " & $MAC & @LF)

_WSACleanup()

Func _SendARP($DestIP)
Local $DestAddress = _inet_addr($DestIP)
Local $tMacAddr = DllStructCreate("BYTE[8]")
Local $aRet = DllCall("Iphlpapi.dll", "DWORD", "SendARP", "ULONG", $DestAddress, "ULONG", 0, "struct*", $tMacAddr, "ULONG*", 8)
Local $sMAC = ""
Switch $aRet[0]
Case 0
For $i = 1 To $aRet[4] - 1
$sMAC &= Hex(DllStructGetData($tMacAddr, 1, $i), 2) & "-"
Next
$sMAC &= Hex(DllStructGetData($tMacAddr, 1, $i), 2)
Return $sMAC
Case 31
Return "ERROR_GEN_FAILURE"
Case 87
Return "ERROR_INVALID_PARAMETER"
Case 1784
Return "ERROR_INVALID_USER_BUFFER"
Case 67
Return "ERROR_BAD_NET_NAME"
Case 1168
Return "ERROR_NOT_FOUND"
EndSwitch
EndFunc
  • Like 1

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Share this post


Link to post
Share on other sites
Chimp

Ok, Thank You.


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

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

    • Spartan117
      By Spartan117
      Hi everyone,
      I wonder if there is a cloud service that can offer a physical server so that AutoIT can turn as it is in a physical machine.
      Thank you
    • Ambient
      By Ambient
      I am trying to build a list from a query run against a sybase db. This part works fine. My problem is this, I want to display values in a list depending 
      on the value of certain fields  i.e. See below which works for two. Unfortunately, I need it to work for 3 values.  I don't know how I can do this for 3.  I did try doing a select case but I was getting errors.
       
      i.e. if value =0  then "Card Check" if Value = - Then "Card Spend" Else "Money Added"
      The below immediate iif works brilliantly for two but as I say I need to build this with 3 different values. 
       
       
      $idItem = GUICtrlCreateListViewItem( _iif($adoRs.Fields("TransactionAmount").value =0, "Card check","Money Added") 
       
      Any help appreciated.
    • ripdad
      By ripdad
      I have had several people ask for this, so I decided to work the algorithm for it and this is the result.
      What is it?
      A Gateway Proxy Sends and Receives Data Unmodified.
      https://en.wikipedia.org/wiki/Proxy_server
      What is it used for?
      You can use it as a gateway, relay or router between two known static IP addresses.
      More information is in the header of the script.
      Download: LocalGatewayProxy.au3
      You will need WSA_NBTCP.au3 from here:
      https://www.autoitscript.com/forum/topic/191954-wsa_nbtcp-v100-udf/
      If you have any questions or problems, let me know.
       
    • ripdad
      By ripdad

      This script is based on algorithm code from EnrMa.
      Updated: January 22, 2018
      Made improvements. Changes are in the script header.
      Known Issues: AutoIt x64 does not work properly with this script.
      Download: LocalProxyServer_v1.00.zip
       
    • ripdad
      By ripdad
      WSA_NBTCP.au3  (Windows Sockets API - Non-Blocking Transmission Control Protocol)
      Version: 1.00
      Type: UDF
      This is an accumulation of WSA code from many sources and modified to suit myself.
      These functions have been thoroughly tested using a Local Proxy Server, which
      is about the most strenuous test you can use.
      Includes my rendition of how a TCPRecv Timeout should work. Also includes a
      timewait/timeout using Select for TCP Send, which works great for that function.
      You will need a loop to use _WSA_TCPRecv(). An example will be forthcoming in a second post.
      Functions:
      #CURRENT_USER_FUNCTIONS
      _WSA_Cleanup
      _WSA_FormatMessage
      _WSA_GetLastError
      _WSA_TCPAccept
      _WSA_TCPCloseSocket
      _WSA_TCPConnect
      _WSA_TCPListen
      _WSA_TCPRecv
      _WSA_TCPSend

      #INTERNAL_FUNCTIONS
      __TimeoutManager
      __TimeoutReset

      #EXTRA_FUNCTIONS
      _WSA_GetAddrInfo
      _WSA_GetHostByAddr
      _WSAAsyncGetHostByName
      _WSAAsyncGetHostByName_Callback
      _WSA_GetNameInfo
       
      Requirements:
      - AutoIt Versions: 3.3.8.1 thru 3.3.15.0 (32Bit only).
      - TCPStartup() at beginning of script on startup.
      - TCPShutDown() and _WSA_Cleanup() on exit.
      Download UDF: WSA_NBTCP.au3
       
×