AutoHotkey Community

It is currently May 26th, 2012, 6:48 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 131 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7, 8, 9  Next
Author Message
 Post subject:
PostPosted: March 31st, 2008, 10:24 pm 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7501
Location: Australia
Quote:
The inet_addr function converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the IN_ADDR structure.
You should be able to manually fill SocketAddress with a sockaddr_in6 structure. The definition is:
Code:
typedef struct sockaddr_in6 {
    ADDRESS_FAMILY sin6_family; // AF_INET6.
    USHORT sin6_port;           // Transport level port number.
    ULONG  sin6_flowinfo;       // IPv6 flow information.
    IN6_ADDR sin6_addr;         // IPv6 address.
    union {
        ULONG sin6_scope_id;     // Set of interfaces for a scope.
        SCOPE_ID sin6_scope_struct;
    };
} SOCKADDR_IN6_LH, *PSOCKADDR_IN6_LH, FAR *LPSOCKADDR_IN6_LH;

typedef struct in6_addr {
    union {
        UCHAR       Byte[16];
        USHORT      Word[8];
    } u;
} IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR;


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 2nd, 2008, 7:37 am 
Offline
User avatar

Joined: May 10th, 2007, 10:54 am
Posts: 649
Location: .switzerland
thx I will try this.

_________________
http://securityvision.ch
AHK 2D GAME ENGINE


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 21st, 2008, 2:04 am 
Offline

Joined: February 6th, 2008, 5:36 am
Posts: 23
Location: Dallas
Hi there, I have been working with this code a bit and had a weird question, .... the problem was the script kept crashing when I close the client script, but if I just did a re-load on the client script the problem goes away.... so thanks very much (!) to the other poster aka. someotherguy who helped me by giving me this _obvious_ clue! :D


Last edited by LYCOS17 on May 1st, 2008, 10:22 am, edited 4 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 30th, 2008, 3:48 pm 
Offline

Joined: February 6th, 2008, 5:36 am
Posts: 23
Location: Dallas
*bump*


Last edited by LYCOS17 on May 1st, 2008, 10:17 am, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 30th, 2008, 8:03 pm 
I am no expert a t this, so i have no general idea.

But if you post your try and the errormessages you get,
it might be easier to analyze that problem.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: April 30th, 2008, 9:09 pm 
Offline

Joined: June 22nd, 2007, 4:42 am
Posts: 40
Thanks a lot for this Zed Gecko, this looks awesome, and thanks LYCOS17 for bumping because I would have never seen this, lol.

_________________
Truth is truth, whether you believe it or not.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 2nd, 2008, 6:35 am 
Offline

Joined: June 22nd, 2007, 4:42 am
Posts: 40
Hi,
I was trying to combine qtmspin's code that allowed multiple users and wtg's code that sent the text to an edit box. I get an error when I send:

Image
(if they take that down, go here http://crash23000.freewebspace.com/TCP_error.JPG

As you can see, it sends the data and works for multiple clients, but still displays an error on send.

Heres the code

Server:
Code:
; -------------------------------------------------
; ------------SERVERSCRIPT------------------
; -------------------------------------------------
; CONFIGURATION SECTION:

; Specify Your own Network's address and port.
Network_Address = 127.0.0.1
Network_Port = 8765
; ----------------------------
; END OF CONFIGURATION SECTION
; ----------------------------

Gui, Add, Text,, Send:
Gui, Add, Edit, w100 vSendText
Gui, Add, Text,, Repeat:
Gui, Add, Edit, w40 vRepeat, 1
Gui, Add, Text,, Delay (ms):
Gui, Add, Edit, w40 vDelay, 0   
Gui, Add, Button, gSendviaNet, Send
Gui, Show

Gosub Connection_Init
return

Connection_Init:
OnExit, ExitSub  ; For connection cleanup purposes.

; set up a very basic server:
socket := PrepareForIncomingConnection(Network_Address, Network_Port)
if socket = -1  ; Connection failed (it already displayed the reason).
    ExitApp

; Find this script's main window:
Process, Exist  ; This sets ErrorLevel to this script's PID (it's done this way to support compiled scripts).
DetectHiddenWindows On
ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel)
DetectHiddenWindows Off

; Set up the connection to notify this script via message whenever new data has arrived.
; This avoids the need to poll the connection and thus cuts down on resource usage.
FD_READ = 1     ; Received when data is available to be read.
;FD_WRITE =
FD_CLOSE = 32   ; Received when connection has been closed.
FD_CONNECT = 20 ; Received when connection has been made.
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_CLOSE|FD_CONNECT)
{
    MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    ExitApp
}


i=1
Loop ; Wait for incomming connections
{
; accept requests that are in the pipeline of the socket   
   conectioncheck%i% := DllCall("Ws2_32\accept", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
; Ws2_22/accept returns the new Connection-Socket if a connection request was in the pipeline
; on failure it returns an negative value
    if conectioncheck%i% > 1
    {
       MsgBox Incoming connection accepted
       i++
    }       
    sleep 500 ; wait half 1 second then accept again
}   
return

SendviaNet:
Gui, Submit, NoHide
Loop %i% {
SendData(conectioncheck%A_Index%,SendText,Repeat,Delay)
}
SentText =
return

PrepareForIncomingConnection(IPAddress, Port)
; This can connect to most types of TCP servers, not just Network.
; Returns -1 (INVALID_SOCKET) upon failure or the socket ID upon success.
{
    VarSetCapacity(wsaData, 32)  ; The struct is only about 14 in size, so 32 is conservative.
    result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData) ; Request Winsock 2.0 (0x0002)
    ; Since WSAStartup() will likely be the first Winsock function called by this script,
    ; check ErrorLevel to see if the OS has Winsock 2.0 available:
    if ErrorLevel
    {
        MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
        return -1
    }
    if result  ; Non-zero, which means it failed (most Winsock functions return 0 upon success).
    {
        MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
        return -1
    }

    AF_INET = 2
    SOCK_STREAM = 1
    IPPROTO_TCP = 6
    socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
    if socket = -1
    {
        MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
        return -1
    }

    ; Prepare for connection:
    SizeOfSocketAddress = 16
    VarSetCapacity(SocketAddress, SizeOfSocketAddress)
    InsertInteger(2, SocketAddress, 0, AF_INET)   ; sin_family
    InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)   ; sin_port
    InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)   ; sin_addr.s_addr

    ; Bind to socket:
    if DllCall("Ws2_32\bind", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
    {
        MsgBox % "bind() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
        return -1
    }
    if DllCall("Ws2_32\listen", "UInt", socket, "UInt", "SOMAXCONN")
    {
        MsgBox % "LISTEN() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
        return -1
    }
   
    return socket  ; Indicate success by returning a valid socket ID rather than -1.
}

SendData(wParam,SendData, Repeat, Delay)
{
   socket := wParam
;   SendDataSize := VarSetCapacity(SendData)
;   SendDataSize += 1
   Loop % Repeat
   {
        SendIt := SendData  ;SendIt := SendData . "(" . A_Index . ")"
      SendDataSize := VarSetCapacity(SendIt)
      SendDataSize += 1
     
      sendret := DllCall("Ws2_32\send", "UInt", socket, "Str", SendIt, "Int", SendDatasize, "Int", 0)
      WinsockError := DllCall("Ws2_32\WSAGetLastError")
      if WinsockError <> 0 ; WSAECONNRESET, which happens when Network closes via system shutdown/logoff.
         ; Since it's an unexpected error, report it.  Also exit to avoid infinite loop.
         MsgBox % "send() indicated Winsock error " . WinsockError
        sleep,Delay
   }     
;send( sockConnected,> welcome, strlen(welcome) + 1, NULL);
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
    Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

guiclose:
ExitSub:  ; This subroutine is called automatically when the script exits for any reason.
; MSDN: "Any sockets open when WSACleanup is called are reset and automatically
; deallocated as if closesocket was called."
DllCall("Ws2_32\WSACleanup")
ExitApp


Client:
Code:
; -------------------------------------------------
;-----------CLIENTSCRIPT----------------------
; -------------------------------------------------
; CONFIGURATION SECTION:

; Specify address and port of the server.
Network_Address = 127.0.0.1
Network_Port = 8765
; ----------------------------
; END OF CONFIGURATION SECTION
; ----------------------------

Gui, Add, Button, gConnection_Init, Connect
Gui, Add, Edit, R10 vMyEdit
Gui, Add, Button, gClear, Clear
Gui, Show

LinesReceived:=0
return

Connection_Init:
OnExit, ExitSub  ; For connection cleanup purposes.

; Connect to any type of server:
socket := ConnectToAddress(Network_Address, Network_Port)
if socket = -1  ; Connection failed (it already displayed the reason).
    ExitApp

; Find this script's main window:
Process, Exist  ; This sets ErrorLevel to this script's PID (it's done this way to support compiled scripts).
DetectHiddenWindows On
ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel)
DetectHiddenWindows Off

; When the OS notifies the script that there is incoming data waiting to be received,
; the following causes a function to be launched to read the data:
NotificationMsg = 0x5555  ; An arbitrary message number, but should be greater than 0x1000.
OnMessage(NotificationMsg, "ReceiveData")

; Set up the connection to notify this script via message whenever new data has arrived.
; This avoids the need to poll the connection and thus cuts down on resource usage.
FD_READ = 1     ; Received when data is available to be read.
FD_CLOSE = 32   ; Received when connection has been closed.
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CLOSE)
{
    MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    ExitApp
}
return

Clear:
ShowReceived=
LinesReceived:=0   
GuiControl,, MyEdit,
return

ConnectToAddress(IPAddress, Port)
; Returns -1 (INVALID_SOCKET) upon failure or the socket ID upon success.
{
    VarSetCapacity(wsaData, 32)  ; The struct is only about 14 in size, so 32 is conservative.
    result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData) ; Request Winsock 2.0 (0x0002)
    ; Since WSAStartup() will likely be the first Winsock function called by this script,
    ; check ErrorLevel to see if the OS has Winsock 2.0 available:
    if ErrorLevel
    {
        MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
        return -1
    }
    if result  ; Non-zero, which means it failed (most Winsock functions return 0 upon success).
    {
        MsgBox % "WSAStartup() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
        return -1
    }

    AF_INET = 2
    SOCK_STREAM = 1
    IPPROTO_TCP = 6
    socket := DllCall("Ws2_32\socket", "Int", AF_INET, "Int", SOCK_STREAM, "Int", IPPROTO_TCP)
    if socket = -1
    {
        MsgBox % "socket() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
        return -1
    }

    ; Prepare for connection:
    SizeOfSocketAddress = 16
    VarSetCapacity(SocketAddress, SizeOfSocketAddress)
    InsertInteger(2, SocketAddress, 0, AF_INET)   ; sin_family
    InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)   ; sin_port
    InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)   ; sin_addr.s_addr

    ; Attempt connection:
    if DllCall("Ws2_32\connect", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
    {
        MsgBox % "connect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
        return -1
    }
    return socket  ; Indicate success by returning a valid socket ID rather than -1.
}

ReceiveData(wParam, lParam)
; By means of OnMessage(), this function has been set up to be called automatically whenever new data
; arrives on the connection.
{
     Critical
    global ShowReceived
    global MyEdit
    global LinesReceived

    socket := wParam
    ReceivedDataSize = 4096  ; Large in case a lot of data gets buffered due to delay in processing previous data.
    VarSetCapacity(ReceivedData, ReceivedDataSize, 0)  ; 0 for last param terminates string for use with recv().
    Data   := ""
    Loop  ; This loop solves the issue of the notification message being discarded due to thread-already-running.
    {
        ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
        if ReceivedDataLength = 0  ; The connection was gracefully closed,
            ExitApp  ; The OnExit routine will call WSACleanup() for us.
        if ReceivedDataLength = -1
        {
            WinsockError := DllCall("Ws2_32\WSAGetLastError")
            if ( WinsockError = 10035 ) { ; WSAEWOULDBLOCK, which means "no more data to be read".
                break
            }
            if WinsockError <> 10054 ; WSAECONNRESET, which happens when Network closes via system shutdown/logoff.
                ; Since it's an unexpected error, report it.  Also exit to avoid infinite loop.
                MsgBox % "recv() indicated Winsock error " . WinsockError
            ExitApp  ; The OnExit routine will call WSACleanup() for us.
        }
        Data .= ReceivedData
    }
    ; Otherwise, process the data received.
    Loop, parse, Data, `n, `r
    {
       LinesReceived++               
        if (LinesReceived = 1) {
           ShowReceived = %LinesReceived%: %A_LoopField%
        } else {
           ShowReceived = %ShowReceived%`n%LinesReceived%: %A_LoopField%
       }
       ;Tooltip % ShowReceived
       GuiControl,, MyEdit, %ShowReceived%
    }
    return 1  ; Tell the program that no further processing of this message is needed.
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
    Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

guiclose:
ExitSub:  ; This subroutine is called automatically when the script exits for any reason.
; MSDN: "Any sockets open when WSACleanup is called are reset and automatically
; deallocated as if closesocket was called."
DllCall("Ws2_32\WSACleanup")
ExitApp


I guess I could comment out the error report since it works anyways, unless it is a serious error, but seems like it isn't because it still sends. I was thinking that it is trying to send to someone who isn't connected but I guess I can't interpret the code good enough to verify my assumptions : / lol.


Thanks for any help

_________________
Truth is truth, whether you believe it or not.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 2nd, 2008, 7:08 am 
since Winsock Error 10038 means Socket operation on non-socket.
Quote:
WSAENOTSOCK
(10038)
Socket operation on non-socket.
An operation was attempted on something that is not a socket. Either the socket handle parameter did not reference a valid socket, or for select, a member of an fd_set was not valid.


You could be right with your assumption:
Quote:
I was thinking that it is trying to send to someone who isn't connected


maybe it just happens after at least one client disconnected?
could you check this out?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: May 2nd, 2008, 7:43 am 
Offline

Joined: June 22nd, 2007, 4:42 am
Posts: 40
The screenshot I took was the server sending "hey" after one client connected, with no disconnects. So I dont think that this is caused by a client disconnecting.

I'm just making another assumption, but I think it has something to do with the code I changed to allow multi-clients.

maybe, either here:
Code:
i=1
Loop ; Wait for incomming connections
{
; accept requests that are in the pipeline of the socket   
   conectioncheck%i% := DllCall("Ws2_32\accept", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
; Ws2_22/accept returns the new Connection-Socket if a connection request was in the pipeline
; on failure it returns an negative value
    if conectioncheck%i% > 1
    {
       MsgBox Incoming connection accepted
       i++
    }       
    sleep 500 ; wait half 1 second then accept again
}   
return

or maybe here:
Code:
SendviaNet:
Gui, Submit, NoHide
Loop %i% {
SendData(conectioncheck%A_Index%,SendText,Repeat,Delay)
}
SentText =
return


I'm guessing that its in one of the spots above, because its the only part of the sending code I changed I think.

_________________
Truth is truth, whether you believe it or not.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 2nd, 2008, 8:22 am 
i think i got it.
Code:
SendviaNet:
Gui, Submit, NoHide
Loop % i - 1
{
SendData(conectioncheck%A_Index%,SendText,Repeat,Delay)
}
SentText =
return
will fix it.

the var "i" is 2 when one client is accepted,
so in the sending loop, the last iteration will fail.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: May 2nd, 2008, 8:54 am 
Offline

Joined: June 22nd, 2007, 4:42 am
Posts: 40
Thanks a lot, this works great, I tried i=0 instead of the i=1 for the 1st part of code I pasted, I should have tried something similar on the 2nd part of code that you fixed, lol.

Thanks a lot though.

_________________
Truth is truth, whether you believe it or not.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: May 3rd, 2008, 1:06 pm 
Hi,

Is it possible to create username and password checker at server side that received from client?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: May 3rd, 2008, 1:32 pm 
I´m not shure what you mean, if you mean to have
the client script send a username and a password to the serverscript,
and the serverscript to cancel the connection when they are wrong.
Then yes, it´s pssible. 8)


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: May 14th, 2008, 6:06 am 
Like the script got a question.I wanted to know if there was anyway to identify the connections coming in. Like associating the incoming socket of the person trying to connect with their IP address. I was trying to make a sort of chat server if you will and in order to make a effective user list, I needed to associate incoming connections with their network address. This way I can slap a nickname on that address and bam the list will work. Also so when the person disconnects it will show their address disconnecting.

I also noticed on that new Close message that Zed posted were he didn't know if it worked or not, when I attempted to add the functions in the script, only 1 of the 2 dll calls (right after the

Code:
FD_READ = 1     ; Received when data is available to be read.
FD_CLOSE = 32   ; Received when connection has been closed.
FD_CONNECT = 20 ; Received when connection has been made.
)
would work. In terms, I could either be notified that the client was disconnecting OR receive the text they send.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: May 19th, 2008, 6:10 am 
Offline

Joined: September 23rd, 2006, 1:58 pm
Posts: 149
Well, i found out, that the getpeername function of Winsock will return the IP-Address of the socket.
But i neither know how to call it properly via DLL-Call, nor do i know how to handle the the struct that is returned.
(Maybe this is helpfull: http://www.autohotkey.com/forum/viewtopic.php?t=27644 )

For the WSASyncSelect problem, i would like to point you to ManaUsers
TCP/Ip Remote-Script, where he shows, how to do it right.

I also want to note, that Zippo() has crated an network-script that can be include, in his C4-Game-script

_________________
code removed due to protest.
http://www.autohotkey.com/forum/viewtopic.php?t=81795


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 131 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7, 8, 9  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Exabot [Bot], mrhobbeys, nothing, siterip, Stigg and 10 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group