Jump to content

Help with TCP


Recommended Posts

I use the Function Reference and got 1 server and 1 client.

-server

#include <GUIConstantsEx.au3>

Opt('MustDeclareVars', 1)

;==============================================
;==============================================
;SERVER!! Start Me First !!!!!!!!!!!!!!!
;==============================================
;==============================================

Example()

Func Example()
    ; Set Some reusable info
    ; Set your Public IP address (@IPAddress1) here.
;   Local $szServerPC = @ComputerName
;   Local $szIPADDRESS = TCPNameToIP($szServerPC)
    Local $szIPADDRESS = @IPAddress1
    Local $nPORT = 33891
    Local $MainSocket, $GOOEY, $edit, $ConnectedSocket, $szIP_Accepted
    Local $msg, $recv

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

    ; Create a Listening "SOCKET".
    ;   Using your IP Address and Port 33891.
    ;==============================================
    $MainSocket = TCPListen($szIPADDRESS, $nPORT)

    ; If the Socket creation fails, exit.
    If $MainSocket = -1 Then Exit


    ; Create a GUI for messages
    ;==============================================
    $GOOEY = GUICreate("My Server (IP: " & $szIPADDRESS & ")", 300, 200)
    $edit = GUICtrlCreateEdit("", 10, 10, 280, 180)
    GUISetState()


    ; Initialize a variable to represent a connection
    ;==============================================
    $ConnectedSocket = -1


    ;Wait for and Accept a connection
    ;==============================================
    Do
        $ConnectedSocket = TCPAccept($MainSocket)
    Until $ConnectedSocket <> -1


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

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

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

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

        ; If the receive failed with @error then the socket has disconnected
        ;----------------------------------------------------------------
        If @error Then ExitLoop

        ; Update the edit control with what we have received
        ;----------------------------------------------------------------
        If $recv <> "" Then GUICtrlSetData($edit, _
                $szIP_Accepted & " > " & $recv & @CRLF & GUICtrlRead($edit))
        
    WEnd


    If $ConnectedSocket <> -1 Then TCPCloseSocket($ConnectedSocket)

    TCPShutdown()
EndFunc   ;==>Example

; Function to return IP Address from a connected socket.
;----------------------------------------------------------------------
Func SocketToIP($SHOCKET)
    Local $sockaddr, $aRet
   
    $sockaddr = DllStructCreate("short;ushort;uint;char[8]")

    $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _
            "ptr", DllStructGetPtr($sockaddr), "int*", DllStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf

    $sockaddr = 0

    Return $aRet
EndFunc   ;==>SocketToIP

-client-

#include <GUIConstantsEx.au3>

Opt('MustDeclareVars', 1)

;==============================================
;==============================================
;CLIENT! Start Me after starting the SERVER!!!!!!!!!!!!!!!
;==============================================
;==============================================

Example()

Func Example()
    ; Set Some reusable info
    ;--------------------------
    Local $ConnectedSocket, $szData
    ; Set $szIPADDRESS to wherever the SERVER is. We will change a PC name into an IP Address
;   Local $szServerPC = @ComputerName
;   Local $szIPADDRESS = TCPNameToIP($szServerPC)
    Local $szIPADDRESS = @IPAddress1
    Local $nPORT = 33891
    local $GOOEY,$edit,$recv
    $GOOEY = GUICreate("My Server (IP: " & $szIPADDRESS & ")", 300, 200)
    $edit = GUICtrlCreateEdit("", 10, 10, 280, 180)
    GUISetState()
    ; Start The TCP Services
    ;==============================================
    TCPStartup()

    ; Initialize a variable to represent a connection
    ;==============================================
    $ConnectedSocket = -1

    ;Attempt to connect to SERVER at its IP and PORT 33891
    ;=======================================================
    $ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)

    ; If there is an error... show it
    If @error Then
        MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)
        ; If there is no error loop an inputbox for data
        ;   to send to the SERVER.
    Else
        ;Loop forever asking for data to send to the SERVER
        While 1
            ; InputBox for data to transmit
            $szData = "hello"

            ; If they cancel the InputBox or leave it blank we exit our forever loop
            If @error Or $szData = "" Then ExitLoop

            ; We should have data in $szData... lets attempt to send it through our connected socket.
            TCPSend($ConnectedSocket, $szData)
            ; If the send failed with @error then the socket has disconnected
            ;----------------------------------------------------------------
            If @error Then ExitLoop
        WEnd
    EndIf
EndFunc   ;==>Example

when I start the client is should send $szData to the server ( witch is "hello") and the server should get it print it in the $edit and make a new line. But it gets like this:

172.16.0.1 > hello

172.16.0.1 > hello

172.16.0.1 > hellohellohellohellohellohellohellohello

172.16.0.1 > hellohellohellohellohellohellohellohello

172.16.0.1 > hellohellohellohellohellohellohellohellohellohellohello

172.16.0.1 > hellohellohellohellohellohellohellohellohellohellohello

172.16.0.1 > hellohellohellohellohellohellohello

172.16.0.1 > hellohello

172.16.0.1 > hello

as you see the server get´s many hello when reciving the data, I think it is becouse the client spamms out so hello so fast maybe like 10 hello before the server can recive them and then it think it is 1 big package of hello, and it print out all on the same line.

I´m a wrong?

how do I make the server know that it is many pageage?

Or, how do I make the client know that the server have got the message and it can send a new one?

I got 1 more problem but let´s solve this first!

All help is appreciated!

Edited by Huggen
Link to comment
Share on other sites

You could cheat a little and have the client send a break character along with the text, like a "|", then do a string split on $recv and parse the resulting array instead of just posting the $recv. I.e.:

For the client:

$szData = "hello" & "|"

For the server:

$recv = StringSplit(TCPRecv($ConnectedSocket, 2048),"|")

        ; If the receive failed with @error then the socket has disconnected
        ;----------------------------------------------------------------
        If @error Then ExitLoop

        ; Update the edit control with what we have received
        ;----------------------------------------------------------------
        If IsArray($recv) Then 
             For $i = 1 to $recv[0]
                   GUICtrlSetData($edit, $szIP_Accepted & " > " & $recv[$i] & @CRLF & GUICtrlRead($edit))
             Next
        EndIf

I haven't tested it, but that should work.

Edit: As I think about it, this wouldn't help you with multiple clients, as they'd all report as coming from the same IP. This would only work if you send the IP data along with the message.

Edited by Frog
Link to comment
Share on other sites

Actully it would work for different Ips, becouse the revc only work for one connection and it will be 2 different connections if 2 clients is connected

and that would solve this but still want need to know how to make it for real

Edited by Huggen
Link to comment
Share on other sites

Hmm.... You could try something like this for the "spamming" problem:

While 1
            ; InputBox for data to transmit
            $szData = "hello"

            ; If they cancel the InputBox or leave it blank we exit our forever loop
            If @error Or $szData = "" Then ExitLoop

            ; We should have data in $szData... lets attempt to send it through our connected socket.
            TCPSend($ConnectedSocket, $szData)
            TCPSend($ConnectedSocket, "")       <--------------------------------------------------- !!!
            ; If the send failed with @error then the socket has disconnected
            ;----------------------------------------------------------------
            If @error Then ExitLoop
        WEnd

So when the message is sendt, it will clear the message sendt via that specific socket! Worked for me! :)

as for the the multi client problem:

While 1
            ; InputBox for data to transmit
            $szData = @IPAddress1 & ": hello"       <--------------------------------------------------- !!!

            ; If they cancel the InputBox or leave it blank we exit our forever loop
            If @error Or $szData = "" Then ExitLoop

            ; We should have data in $szData... lets attempt to send it through our connected socket.
            TCPSend($ConnectedSocket, $szData)
            TCPSend($ConnectedSocket, "")
            ; If the send failed with @error then the socket has disconnected
            ;----------------------------------------------------------------
            If @error Then ExitLoop
        WEnd

It would work for a LAN, but via the internet, I am not sure how the @IPAddress1 macro works. Possibly it would only send its local ip(ex: 192.168.0.124) and that would not help you in any way... :S

You could use the SocketToIP function, but that would require you to make uniqe handles for each connected client, for example that every client would be stored in an array, I belive. But then you would have challenges like: handing out id's to the clients, closing spec sockets as they disconnect, and so on...

Hope that this was of some help! =)

EDIT: Fixed a formatting problem.

Edited by sloppyprogrammer

[center]They say that there is only 10 kinds of people that understand binary code; those who do, and those who don't...[/center][center]Get it? :P[/center]

Link to comment
Share on other sites

Actully it would work for different Ips, becouse the revc only work for one connection and it will be 2 different connections if 2 clients is connected

and that would solve this but still want need to know how to make it for real

You're right, it would just be one IP, so there would be no problem. Adding a split character will work, then. I just tested it, and it does fix your spam problem.

Link to comment
Share on other sites

Get the server to reply to the client telling the client the string length received will stop your multiple hello's.

This should get you going, you might want to add a timeout on the client side for waiting for a reply.

Edit. What on Earth happened to my AutoIT code formatting???? fixed it, paste from notepad not Scite

Client

#include <GUIConstantsEx.au3>

Opt('MustDeclareVars', 1)

;==============================================
;==============================================
;CLIENT! Start Me after starting the SERVER!!!!!!!!!!!!!!!
;==============================================
;==============================================

Example()

Func Example()
    ; Set Some reusable info
    ;--------------------------
    Local $ConnectedSocket, $szData
    ; Set $szIPADDRESS to wherever the SERVER is. We will change a PC name into an IP Address
;   Local $szServerPC = @ComputerName
;   Local $szIPADDRESS = TCPNameToIP($szServerPC)
    Local $szIPADDRESS = @IPAddress1
    Local $nPORT = 33891
    local $GOOEY,$edit,$recv
    $GOOEY = GUICreate("My Server (IP: " & $szIPADDRESS & ")", 300, 200)
    $edit = GUICtrlCreateEdit("", 10, 10, 280, 180)
    GUISetState()
    ; Start The TCP Services
    ;==============================================
    TCPStartup()

    ; Initialize a variable to represent a connection
    ;==============================================
    $ConnectedSocket = -1

    ;Attempt to connect to SERVER at its IP and PORT 33891
    ;=======================================================
    $ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)

    ; If there is an error... show it
    If @error Then
        MsgBox(4112, "Error", "TCPConnect failed with WSA error: " & @error)
        ; If there is no error loop an inputbox for data
        ;   to send to the SERVER.
    Else
        ;Loop forever asking for data to send to the SERVER
        While 1
            ; InputBox for data to transmit
            $szData = "hello"

            ; If they cancel the InputBox or leave it blank we exit our forever loop
            If @error Or $szData = "" Then ExitLoop

            ; We should have data in $szData... lets attempt to send it through our connected socket.
            TCPSend($ConnectedSocket, $szData)
            
            ;Now wait for a reply from the server confirming we have sent the data OK
            Local $reply = 0
            While $reply =0
                $reply = TCPRecv($ConnectedSocket,4)
                If @error Then ExitLoop
            WEnd
            
            If StringLen($szData) = $Reply then Msgbox(0,"","Correct amount of data hit the server")
                
            ; If the send failed with @error then the socket has disconnected
            ;----------------------------------------------------------------
            If @error Then ExitLoop
        WEnd
    EndIf
EndFunc   ;==>Example

Server

#include <GUIConstantsEx.au3>

Opt('MustDeclareVars', 1)

;==============================================
;==============================================
;SERVER!! Start Me First !!!!!!!!!!!!!!!
;==============================================
;==============================================

Example()

Func Example()
    ; Set Some reusable info
    ; Set your Public IP address (@IPAddress1) here.
;   Local $szServerPC = @ComputerName
;   Local $szIPADDRESS = TCPNameToIP($szServerPC)
    Local $szIPADDRESS = @IPAddress1
    Local $nPORT = 33891
    Local $MainSocket, $GOOEY, $edit, $ConnectedSocket, $szIP_Accepted
    Local $msg, $recv

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

    ; Create a Listening "SOCKET".
    ;   Using your IP Address and Port 33891.
    ;==============================================
    $MainSocket = TCPListen($szIPADDRESS, $nPORT)

    ; If the Socket creation fails, exit.
    If $MainSocket = -1 Then Exit


    ; Create a GUI for messages
    ;==============================================
    $GOOEY = GUICreate("My Server (IP: " & $szIPADDRESS & ")", 300, 200)
    $edit = GUICtrlCreateEdit("", 10, 10, 280, 180)
    GUISetState()


    ; Initialize a variable to represent a connection
    ;==============================================
    $ConnectedSocket = -1


    ;Wait for and Accept a connection
    ;==============================================
    Do
        $ConnectedSocket = TCPAccept($MainSocket)
    Until $ConnectedSocket <> -1


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

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

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

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

        ; If the receive failed with @error then the socket has disconnected
        ;----------------------------------------------------------------
        If @error Then ExitLoop

        ; Update the edit control with what we have received
        ;----------------------------------------------------------------
        If $recv <> "" Then GUICtrlSetData($edit, _
                $szIP_Accepted & " > " & $recv & @CRLF & GUICtrlRead($edit))
                TCPSend($ConnectedSocket,StringLen($recv)) ;Reply to the client telling them how much data we received
        
    WEnd


    If $ConnectedSocket <> -1 Then TCPCloseSocket($ConnectedSocket)

    TCPShutdown()
EndFunc   ;==>Example

; Function to return IP Address from a connected socket.
;----------------------------------------------------------------------
Func SocketToIP($SHOCKET)
    Local $sockaddr, $aRet
   
    $sockaddr = DllStructCreate("short;ushort;uint;char[8]")

    $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _
            "ptr", DllStructGetPtr($sockaddr), "int*", DllStructGetSize($sockaddr))
    If Not @error And $aRet[0] = 0 Then
        $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
        If Not @error Then $aRet = $aRet[0]
    Else
        $aRet = 0
    EndIf

    $sockaddr = 0

    Return $aRet
EndFunc   ;==>SocketToIP
Edited by ChrisL
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...