Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

Fast multi-client TCP server

tcp server

  • Please log in to reply
38 replies to this topic

#1 Kealper

Kealper

    Wayfarer

  • Active Members
  • Pip
  • 90 posts

Posted 04 February 2012 - 01:39 AM

I've had this thing I wrote up laying around for a while now and decided I'd comment the heck out of it and post it here for others to enjoy as well.

It's a multi-client TCP server "base" that has all the boilerplate code done, the only thing that one needs to do is just whip their protocol code in to it and it's ready to go. I've included a little few-line example bit in it (in the #region stuff) for a simple echo server. A quick way to see the example work is to just start this up and use a telnet client to connect to it on the port that you chose to have it bind (default in the one I'm posting is port 8080), typing a sentence, and pressing enter. This server makes use of setting the TCPTimeout option to 0, making it quite efficient when a high number of clients are connected and making it faster at accepting new connections. It does not use a fixed-size array for storing client connections, but instead dynamically re-sizes the client array when clients disconnect or connect (Setting $MaxClients to 0 makes the number of simultaneous clients only limited by RAM or AutoIt internal limits, whatever is reached first. I've tested this at 10,000 concurrent connections successfully, albeit with some slightly elevated CPU usage :P ). The server also implements a simple per-client packet buffer (as shown in the little echo example) which can come in handy for things such as large packets from file transferring and such. Instead of only relying on checking @error after a TCPRecv call to determine if a client disconnected (which can lie in certain cases), this uses a checking function which implements both that @error check and an idle timeout check that disconnects the client if they have not sent anything in a certain period of time.

This is not really aimed at people who are unfamiliar with sockets work in AutoIt, as this provides no real application layer protocol, you must make that yourself. The only thing this does is do all the hard and/or tedious work of managing what happens when clients try connecting, how packet data should be buffered, and when a connection should be considered "dead".

If you use this in a project, a simple little comment saying you used it would be nice :P

AutoIt         
#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.8.1 Author:      Ken Piper Script Function:     Template multi-client server base code.     Use as a base for making an efficient server program.     This base will just accept connections and echo back what it receives,         and kill the connection if it is dead or inactive for x seconds.     It will not do any other work, that must be added seperately! #ce ---------------------------------------------------------------------------- TCPStartup() Opt("TCPTimeout", 0) #region ;Safe-to-edit things are below Global $BindIP = "0.0.0.0"    ;Listen on all addresses Global $BindPort = 8080        ;Listen on port 8080 Global $Timeout = 15000        ;Max idle time is 15 seconds before calling a connection "dead" Global $PacketSize = 2048    ;Max packet size per-check is 2KB Global $MaxClients = 50        ;Max simultaneous clients is 50 #endregion ;Stuff you shouldn't touch is below Global $Listen Global $Clients[1][4] ;[Index][Socket, IP, Timestamp, Buffer] Global $Ws2_32 = DllOpen("Ws2_32.dll") ;Open Ws2_32.dll, it might get used a lot Global $NTDLL = DllOpen("ntdll.dll") ;Open ntdll.dll, it WILL get used a lot Global $CleanupTimer = TimerInit() ;This is used to time when things should be cleaned up OnAutoItExitRegister("Close") ;Register this function to be called if the server needs to exit $Clients[0][0] = 0 $Listen = TCPListen($BindIP, $BindPort, $MaxClients) ;Start listening on the given IP/port If @error Then Exit 1 ;Exit with return code 1 if something was already bound to that IP and port While 1     USleep(5000, $NTDLL) ;This is needed because TCPTimeout is disabled. Without this it will run one core at ~100%.     ;The USleep function takes MICROseconds, not milliseconds, so 1000 = 1ms delay.     ;When working with this granularity, you have to take in to account the time it takes to complete USleep().     ;1000us (1ms) is about as fast as this should be set. If you need more performance, set this from 5000 to 1000,     ;but doing so will make it consume a bit more CPU time to get that extra bit of performance.     Check() ;Check recv buffers and do things     If TimerDiff($CleanupTimer) > 1000 Then ;If it has been more than 1000ms since Cleanup() was last called, call it now         $CleanupTimer = TimerInit() ;Reset $CleanupTimer, so it is ready to be called again         Cleanup() ;Clean up the dead connections     EndIf     Local $iSock = TCPAccept($Listen) ;See if anything wants to connect     If $iSock = -1 Then ContinueLoop ;If nothing wants to connect, restart at the top of the loop     Local $iSize = UBound($Clients, 1) ;Something wants to connect, so get the number of people currently connected here     If $iSize - 1 > $MaxClients And $MaxClients > 0 Then ;If $MaxClients is greater than 0 (meaning if there is a max connection limit) then check if that has been reached         TCPCloseSocket($iSock) ;It has been reached, close the new connection and continue back at the top of the loop         ContinueLoop     EndIf     ReDim $Clients[$iSize + 1][4] ;There is room for a new connection, allocate space for it here     $Clients[0][0] = $iSize ;Update the number of connected clients     $Clients[$iSize][0] = $iSock ;Set the socket ID of the connection     $Clients[$iSize][1] = SocketToIP($iSock, $Ws2_32) ;Set the IP Address the connection is from     $Clients[$iSize][2] = TimerInit() ;Set the timestamp for the last known activity timer     $Clients[$iSize][3] = "" ;Blank the recv buffer WEnd Func Check() ;Function for processing     If $Clients[0][0] < 1 Then Return ;If there are no clients connected, stop the function right now     For $i = 1 To $Clients[0][0] ;Loop through all connected clients         $sRecv = TCPRecv($Clients[$i][0], $PacketSize) ;Read $PacketSize bytes from the current client's buffer         If $sRecv <> "" Then $Clients[$i][3] &= $sRecv ;If there was more data sent from the client, add it to the buffer         If $Clients[$i][3] = "" Then ContinueLoop ;If the buffer is empty, stop right here and check more clients         $Clients[$i][2] = TimerInit() ;If it got this far, there is data to be parsed, so update the activity timer         #region ;Example packet processing stuff here. This is handling for a simple "echo" server with per-packet handling             $sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], @CRLF, 0, -1)) ;Pull all data to the left of the last @CRLF in the buffer             ;This does NOT pull the first complete packet, this pulls ALL complete packets, leaving only potentially incomplete packets in the buffer             If $sRecv = "" Then ContinueLoop ;Check if there were any complete "packets"             $Clients[$i][3] = StringTrimLeft($Clients[$i][3], StringLen($sRecv) + 1) ;remove what was just read from the client's buffer             $sPacket = StringSplit($sRecv, @CRLF, 1) ;Split all complete packets up in to an array, so it is easy to work with them             For $j = 1 To $sPacket[0] ;Loop through each complete packet; This is where any packet processing should be done                 TCPSend($Clients[$i][0], "Echoing line: " & $sPacket[$j] & @CRLF) ;Echo back the packet the client sent             Next         #endregion ;Example     Next EndFunc Func Cleanup() ;Clean up any disconnected clients to regain resources     If $Clients[0][0] < 1 Then Return ;If no clients are connected then return     Local $iNewSize = 0     For $i = 1 To $Clients[0][0] ;Loop through all connected clients         $Clients[$i][3] &= TCPRecv($Clients[$i][0], $PacketSize) ;Dump any data not-yet-seen in to their recv buffer         If @error Or TimerDiff($Clients[$i][2]) > $Timeout Then ;Check to see if the connection has been inactive for a while or if there was an error             TCPCloseSocket($Clients[$i][0]) ;If yes, close the connection             $Clients[$i][0] = -1 ;Set the socket ID to an invalid socket         Else             $iNewSize += 1         EndIf     Next     If $iNewSize < $Clients[0][0] Then ;If any dead connections were found, drop them from the client array and resize the array         Local $iSize = UBound($Clients, 2) - 1         Local $aTemp[$iNewSize + 1][$iSize + 1]         Local $iCount = 1         For $i = 1 To $Clients[0][0]             If $Clients[$i][0] = -1 Then ContinueLoop             For $j = 0 To $iSize                 $aTemp[$iCount][$j] = $Clients[$i][$j]             Next             $iCount += 1         Next         $aTemp[0][0] = $iNewSize         $Clients = $aTemp     EndIf EndFunc Func Close()     DllClose($Ws2_32) ;Close the open handle to Ws2_32.dll     DllClose($NTDLL) ;Close the open handle to ntdll.dll     For $i = 1 To $Clients[0][0] ;Loop through the connected clients         TCPCloseSocket($Clients[$i][0]) ;Force the client's connection closed     Next     TCPShutdown() ;Shut down networking stuff EndFunc Func SocketToIP($iSock, $hDLL = "Ws2_32.dll") ;A rewrite of that _SocketToIP function that has been floating around for ages     Local $structName = DllStructCreate("short;ushort;uint;char[8]")     Local $sRet = DllCall($hDLL, "int", "getpeername", "int", $iSock, "ptr", DllStructGetPtr($structName), "int*", DllStructGetSize($structName))     If Not @error Then         $sRet = DllCall($hDLL, "str", "inet_ntoa", "int", DllStructGetData($structName, 3))         If Not @error Then Return $sRet[0]     EndIf     Return "0.0.0.0" ;Something went wrong, return an invalid IP EndFunc Func USleep($iUsec, $hDLL = "ntdll.dll") ;A rewrite of the _HighPrecisionSleep function made by monoceres (Thanks!)     Local $hStruct = DllStructCreate("int64")     DllStructSetData($hStruct, 1, -1 * ($iUsec * 10))     DllCall($hDLL, "dword", "ZwDelayExecution", "int", 0, "ptr", DllStructGetPtr($hStruct)) EndFunc



Comments, questions, and criticisms are appreciated!

(Edited to clear up formatting a bit in the [autoit] tags)
(Edited again to fix a bug in how it cleaned up the connection, and fixed a spelling error in the post)
(Edited once more to fix a very rare corner-case that could happen when getting many connections and disconnections in a short amount of time)
(Edited a bit of code to fix issues with reading multiple buffered packets)
(Edited yet again to fix some spelling in the post and clean the code a bit; I try to keep this code up-to-date with the source file on my computer :P )
(Edited to add a massive performance increase when handling large numbers of connected clients and the client array needs to be trimmed. I've seen up to a 500x speed increase on my computer!)
(Edited again, apparently I forgot to set the max pending connections in TCPListen, leading for some pretty slow connection-accepting! Sorry about that.)

Edited by Kealper, 15 December 2012 - 10:44 AM.

  • Xandy, header127 and JonBMN like this
Posted Image







#2 jmon

jmon

    Adventurer

  • Active Members
  • PipPip
  • 108 posts

Posted 06 February 2012 - 11:33 AM

The code is very clean and easy to understand, I learnt a lot from reading those comments you added. Thanks.

It works very well to. No problem found yet.

Can I set the tcplisten to listen for a limited range of IP adresses ( like : 192.168.0.0 to 50 ) ?

Edited by jmon, 06 February 2012 - 11:38 AM.


#3 hamster

hamster

    Seeker

  • Active Members
  • 8 posts

Posted 07 February 2012 - 06:06 PM

Nice code, also very CPU friendly... However, I think I found a bug. When there is connected more than one client and one of the clients becomes inactive for the timeout period, the Cleanup() function results in the following error:

C:...test.au3 (92) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
$aTemp[$iCount][$j] = $Clients[$i][$j]
^ ERROR
->18:56:20 AutoIT3.exe ended.rc:1
>Exit code: 1 Time: 291.496



#4 Kealper

Kealper

    Wayfarer

  • Active Members
  • Pip
  • 90 posts

Posted 20 March 2012 - 10:21 PM

Hmm... seems the forum doesn't automatically subscribe you to posts that you make... never got any emails about responses, sorry!

Can I set the tcplisten to listen for a limited range of IP adresses ( like : 192.168.0.0 to 50 ) ?

Yes, but you would have to put the code to check if $iSock was equal to IPs in that range right before it set up the connection stuff (just after the check to make sure there is room for new clients, but before it starts setting everything into the $Clients array)
If Not StringRegExp(SocketToIP($iSock), "^192.168.0.[0-50]$") Then TCPCloseSocket($iSock) ;Kill any connections not on the LAN


As for that bug, I noticed that as well while making a web server but I had forgot about this post so I didn't post the updates... It's a corner-case that happens when the Cleanup() function is called while the server is still working with data from that connection, and the connection has already been closed by the client. I'll update the code in the first post as soon as I post this! :oops:

EDIT: Ok, fixed and tested the above code, instead of having Cleanup() called on a timer with AdlibRegister, it is now using a timer and gets called every 1000ms, and that only happens after it has checked all active connections. I'll also keep a better eye on this thread in the future!

Edited by Kealper, 20 March 2012 - 10:35 PM.

Posted Image

#5 bluechipps

bluechipps

    Seeker

  • Active Members
  • 14 posts

Posted 21 March 2012 - 12:03 AM

hey thanks for bumping this, really helpful code and just what i been looking for :oops:

#6 Kealper

Kealper

    Wayfarer

  • Active Members
  • Pip
  • 90 posts

Posted 22 March 2012 - 10:20 AM

hey thanks for bumping this, really helpful code and just what i been looking for :oops:

No problem, glad it helped!

I fixed a small bug which could cause a crash if a lot of connections and disconnections were happening. I've updated the source in the original post, and below is the section of code that I fixed.

This is in the bottom of the Cleanup() function, the part that resizes the $Clients array:
If $bTrim Then     Local $iSize = UBound($Clients, 2) ;This line was modified     Local $iCount = 1     Local $aTemp[1][$iSize]     For $i = 1 To $Clients[0][0]         If $Clients[$i][0] >= 0 Then             ReDim $aTemp[$iCount + 1][$iSize]             For $j = 0 To $iSize - 1 ;This line was modified                 $aTemp[$iCount][$j] = $Clients[$i][$j]             Next             $iCount += 1         EndIf     Next     $aTemp[0][0] = UBound($aTemp, 1) - 1     $Clients = $aTemp EndIf

Posted Image

#7 LeCarre

LeCarre

    Seeker

  • Active Members
  • 16 posts

Posted 22 June 2012 - 01:15 AM

Nice Code.
Used as a foundation for my own server, which is very Raw at the moment.
And i know it's a foundation, and works as an echo server, but has issues when built upon.
So i'd like to suggest a few tweaks

So far my client only sends a login, password like so. function adds @CRLF's

SendTCP($ProtoByte & "Login")
SendTCP($ProtoByte & "Password")

When the server recieved the first batch of bytes, it actually read all of both messages and the server failed, simple changes
will allow users to expand the server with alot less headache ;)

All issues in Func Check()

#1
$sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], @CRLF, 0, -1)) ;Pull all data to the left of the last @CRLF in the buffer

Pulls on the last CRLF, should pull the first, when it recieved both login and password it pulled both. Should Pull only 1 at a time.

Fixed Changed -1 to 1

#2
$Clients[$i][3] = StringTrimLeft($Clients[$i][3], StringLen($sRecv) + 2) ;remove what was just read from the client's buffer
The +2 works with just 1 message in the buffer, but was nibbling into my 2nd message.

Fixed Changed +2 to +1

#3
Definately not a EchoServer issue, but nice to add as a foundation feature is the ability to parse multiple commands at once.
When I got to Pulling Messages correctly it did not parse the second message because the code only has 1 chance per call to parse
anything. As is, it failed to parse the second command in the buffer until more data was recieved from the client.
Adding a simple While 1 Loop checks that all messages are processed immediately.

#4 Is just a nitpick, but as a foundation, terminology could be improved by changing "packets" to "Messages" as we don't want to confuse
people that know what a net traffic packet is.

Provided Code

     #region ;Example packet processing stuff here. This is handling for a simple "echo" server      $sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], @CRLF, 0, -1)) ;Pull all data to the left of the last @CRLF in the buffer      If $sRecv = "" Then ContinueLoop ;Check if there were any complete "packets"      $Clients[$i][3] = StringTrimLeft($Clients[$i][3], StringLen($sRecv) + 2) ;remove what was just read from the client's buffer      TCPSend($Clients[$i][0], "Echo: " & $sRecv & @CRLF) ;Echo back what the client sent      #endregion ;Example


improved Code

     #region ;Example message processing stuff here. This is handling for a simple "echo" server      While 1 ; While Messages are found           $sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], @CRLF, 0, 1)) ;Pull all data to the left of the First @CRLF in the buffer           If $sRecv = "" Then ExitLoop ;Check if there were any complete "messages"           $Clients[$i][3] = StringTrimLeft($Clients[$i][3], StringLen($sRecv) +1 ) ;remove what was just read from the client's buffer           TCPSend($Clients[$i][0], "Echo: " & $sRecv & @CRLF) ;Echo back what the client sent      wend #endregion ;Example

Edited by LeCarre, 22 June 2012 - 01:33 AM.


#8 Kealper

Kealper

    Wayfarer

  • Active Members
  • Pip
  • 90 posts

Posted 04 July 2012 - 07:10 PM

Thanks for pointing those out, admittedly, the simple echo server stuff was added after-the-fact at like 4-5 in the morning so a friend could see some basic example for using it. I'm a bit embarrassed that I didn't catch those before posting this originally... As for the issue of not reading the entire buffer, I hadn't even noticed that at the time I wrote the example buffer code, I'll update the original post with the fixes later today, I'm not at a place where I can test the code edits currently.
Posted Image

#9 Kealper

Kealper

    Wayfarer

  • Active Members
  • Pip
  • 90 posts

Posted 05 July 2012 - 08:26 PM

Ok, finally got around to fixing that...

$sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], @CRLF, 0, -1))

This is intended, it grabs all complete packets from the buffer and leaves any incomplete packets in the buffer, so if the client is still sending a large amount of data, it lets that packet get received completely while it is off checking other things. Actually parsing the packets is left up to the person implementing this in to their own project, but making a parser is fairly trivial, and can be done by using StringSplit($sRecv, @CRLF, 1) to create an array, where each element is a complete packet... From there you just have to loop through the array and process the packets as-necessary. This ensures that only a string of complete, ready-to-be-parsed packets are given to your own code, because crashes are bad :P

The StringTrimLeft thing that removed the already-read packets from the buffer was an error which was taken care of. Finally the error of it skipping over buffered data until new data was received is also fixed, seems I just forgot to have it check the buffer and instead had it checking the data right out of TCPRecv.

The code in the original post has been updated with these fixes, and thanks a lot for pointing out those bugs, they were pretty serious ones and I'm surprised I missed them! :thumbsup:

Edited by Kealper, 05 July 2012 - 08:28 PM.

Posted Image

#10 mb2

mb2

    Seeker

  • Normal Members
  • 3 posts

Posted 15 July 2012 - 08:57 PM

Tnx for this code, will be using this!

But as Lecarre said before, the following should be changed.

#1 $sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], @CRLF, 0, -1)) ;Pull all data to the left of the last @CRLF in the buffer Pulls on the last CRLF, should pull the first, when it recieved both login and password it pulled both. Should Pull only 1 at a time. Fixed Changed -1 to 1


#region ;Example message processing stuff here. This is handling for a simple "echo" server      While 1 ; While Messages are found           $sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], @CRLF, 0, 1)) ;Pull all data to the left of the First @CRLF in the buffer           If $sRecv = "" Then ExitLoop ;Check if there were any complete "messages"           $Clients[$i][3] = StringTrimLeft($Clients[$i][3], StringLen($sRecv) +1 ) ;remove what was just read from the client's buffer           TCPSend($Clients[$i][0], "Echo: " & $sRecv & @CRLF) ;Echo back what the client sent      wend #endregion ;Example


Using -1 will give problems when reveiving multiple packets from the buffer.

#11 mb2

mb2

    Seeker

  • Normal Members
  • 3 posts

Posted 15 July 2012 - 09:00 PM

I could not figure out how to receive complete packets without this change ?

#12 Kealper

Kealper

    Wayfarer

  • Active Members
  • Pip
  • 90 posts

Posted 15 July 2012 - 11:12 PM

I've stated my reason for doing the buffer like I did, and that reason is that this is only the boiler-plate code with a very basic example. If that implementation is not what you are looking for, then making it work for your specific use-case is entirely up to you :P
Although, I would not mind helping you with that if you need it.
Posted Image

#13 mb2

mb2

    Seeker

  • Normal Members
  • 3 posts

Posted 18 July 2012 - 09:47 PM

Well I think finaly got it working.
Changed back again to your original code and if a send a few packets, no problem but when sending lots of packets then somehow on every packet i mis one character.
Maby i'm doing something wrong or i don't understand how correctly split the data.

After making a few minor changes it finaly worked for me.
Global $PacketEndTag = "<END>" Global $PacketEndTagLen = StringLen($PacketEndTag) check() $sRecv = StringLeft($Clients[$i][3], StringInStr($Clients[$i][3], $PacketEndTag, 1, -1) -1) $Clients[$i][3] = StringTrimLeft($Clients[$i][3], StringLen($sRecv) + ($PacketEndTagLen + 0))  ;instead of +1 use the lengt of the packet endtag, this puls the full packet from buffer.


Instead using @CR changed to a variable, makes it more easy for testing and to customise endtag but maby bad for performance ?

But most important change for me is on the second line + 0, instead of +1, now this pulls the complete packet including the endtag.
This way it is possible to split complete packets using stringsplit function, without losing a character on every packet even when buffer is filling up.

I test this using telnet and copy past a file containing lots of bugus data '01234567890<END>'

Anyhow I like your code but maby a few small changes makes it a bit more easy to work with, you don't want to know how much time it cost me :) :)

#14 Valiant8086

Valiant8086

    Seeker

  • Active Members
  • 10 posts

Posted 18 July 2012 - 10:31 PM

Hi.

I've also started trying to use this. I first tried making one of my own, but the server kept on becoming non functional after having ran for a few minutes with no activity. The client would think it connected to the server, but the server would not mention that the client had connected and wouldn't respond to any of the client's requests like it was supposed to, but if I kept using the server from the client, it would work fine. I wonder if it had something to do with dead connections not dropping or what ever, something this server you have here looks to have solved.

So that was when I started looking around to see if I could find some code where hopefully someone else had done that work for me, and the first thing I found was the event driven UDF that's also on this forum. I think if it had worked, I would have really liked that option. I ported my server and client to use it's implementation, and the server and client correctly identified when one another disconnected and connected, but neither ever managed to send messages back and forth at any time.

So I gave up on that one and found this one. I posted a comment on that event driven UDF's topic asking for help, bt no replies yet so I am trying this one. Well I have my server based on this code working fine. I have not really changed the client much. I can't send messages to this server either. I can telnet messages to the server all day long but cannot get my own client to work. Does anyone have an example client that should work with this server implementation?

#15 Kealper

Kealper

    Wayfarer

  • Active Members
  • Pip
  • 90 posts

Posted 18 July 2012 - 11:00 PM

I can telnet messages to the server all day long but cannot get my own client to work.


Would you mind posting your client code so I could give it a stern looking-at, to see if I could spot the problem? If you'd rather not post it here, sending it in a PM to me would work as well... If telnetting to it works fine and the client doesn't, it sounds like the problem is with the client.
Posted Image

#16 Valiant8086

Valiant8086

    Seeker

  • Active Members
  • 10 posts

Posted 18 July 2012 - 11:01 PM

I can't figure out how to edit my previous post.

I created another client using example code from the autoit help file and it doesn't even connect to my server that uses this code. Weird. Telnet still connects and properly sends messages and receives them with this server, but none of my clients, in several different codebases, work well with it. All of them do connect though except the one that's based off the autoit example code.

If somebody had a client that they know works with this server and could share it, I could try that and see if it works. I'm sure stuck.

Thanks again.

PS. Why does this post have an edit link and the one above doesn't?

Edited by Valiant8086, 18 July 2012 - 11:03 PM.


#17 Valiant8086

Valiant8086

    Seeker

  • Active Members
  • 10 posts

Posted 18 July 2012 - 11:24 PM

One of the client attempts is below. This is the one based off the autoit help file example. This should work because my server will throw up message boxes along with the one this client throws up, if it connects that is. For me, this client here gives the same error if the server is not running as it does if it is, 10023 I think it is. I don't think it's something quite as simple as I typed the IP or port wrong, that's the same IP and port I use with telnet, unless it's something like I need to not have quotes around them or something, lol. If I could, I'd fire up a server and see if anyone else could get anything out of it, but my connections are natted even before you get to my routers, both of them are. The intent I have is to run the server on a friend's computer to have it perform, with the friend's permission, more internet heavy tasks. Converting of large files into smaller ones, things like that, because my internet sucks and has low data caps.

Thanks for any assistance.


TCPStartup()
$ConnectedSocket = TCPConnect("127.0.0.1", "25999")
If @error Then
MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)
Else
While 1
$szData = InputBox("Data for Server", @LF & @LF & "Enter data to transmit to the SERVER:")
If @error Or $szData = "" Then ExitLoop
TCPSend($ConnectedSocket, StringToBinary($szData, 4))
If @error Then ExitLoop
WEnd
EndIf

This, by the way, is just an attempt to get it working. I thought I'd start with the down to level raw auto it code again.

P.S. Does anybody know off hand if it's possible to get the mobile version of this forum to run in a full pc web browser? This site seems to be awfully large and sluggish. And the tool bar thing with all those edit controls keeps coming up even though I collapse it.

Here's another edit: I knew I must have done something wrong with the example I posted above. I forgot to put TCPStartup() at the top. I'm putting it in there now. NSice I did that, I can now connect, but like with the other clients, can't get messages to register on the server. The client now shows the input box and sends up a new one when I type something and hit ok, but the server does nothing. wher with telnet if I where to type hi the server would throw up a message box saying "hi".

Edited by Valiant8086, 18 July 2012 - 11:34 PM.


#18 Kealper

Kealper

    Wayfarer

  • Active Members
  • Pip
  • 90 posts

Posted 18 July 2012 - 11:32 PM

If that is all your code, try putting TCPStartup() as the first line, that is needed to initialize sockets in AutoIt...

Below is something I just whipped up that should work with the default example in the original post, although I have not actually tested this, it will at least give you an idea on what's what.

TCPStartup() HotKeySet("{F5}", "SendData") Global $Sock = TCPConnect("127.0.0.1", 8080) While 1     Local $sRecv = TCPRecv($Sock, 8192)     If $sRecv = "" Then ContinueLoop     MsgBox(4096, "Server Reply", $sRecv) WEnd Func SendData()     Local $sData = InputBox("Send To Server", "Enter the string of data you wish to send to the server...")     If $sData = "" Then Return     TCPSend($Sock, $sData & @CRLF) EndFunc


After it runs, press F5 to bring up an input box, enter something simple in to it like "Hello" or such and press enter... you should instantly see a message box pop up saying the text you just sent to the server (which it echoed back).
Posted Image

#19 Valiant8086

Valiant8086

    Seeker

  • Active Members
  • 10 posts

Posted 19 July 2012 - 12:10 AM

Thanks, looks like all I needed was @crlf at the end of the sent message.

Huge help. Thanks much.

#20 Attckdog

Attckdog

    Wayfarer

  • Active Members
  • Pip
  • 84 posts

Posted 26 July 2012 - 01:29 AM

Would it be apporitate to use this UDF to create a login server? I think it would be cool to have this on hand if I end up working on an Autoit game with multiplayer support.
Code looks pretty impressive!
A true renaissance man





Also tagged with one or more of these keywords: tcp, server

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users