AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Client & Server Script for TCP/IP Network Communication
Goto page 1, 2, 3, 4, 5, 6, 7  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Zed Gecko



Joined: 23 Sep 2006
Posts: 98

PostPosted: Thu Nov 02, 2006 4:00 pm    Post subject: Client & Server Script for TCP/IP Network Communication Reply with quote

I managed to modify the Winlirc-Script
http://www.autohotkey.com/docs/scripts/WinLIRC.htm
with the help of this article: http://www.microsoft.com/germany/technet/datenbank/articles/600854.mspx
(sorry only German), and now i can proudly present:
TCP/IP Network Communication without extra Tools
Client- and Server-Script

Full 2-way communication between 2 Scripts only using DLL Calls of Ws2_32.dll (Winsock 2.0). No extra Tools or support-dlls needed, no Command Line. And it is possible to modify the server-script to handle more than one communication parallel.

The examples are very simple: a Textbox whose contents will be shown in a Tooltip on the remote-computer when pressing send button. (the client script has a connect-button in addition)

You will notice, that it took only 4 more DLL-Calls to make the Winlirc-Script into a general Client-Server-Script

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, Edit, w100 vSendText
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

; 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.
FD_CONNECT = 20 ; Recieved when connection has been made.
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CLOSE|FD_CONNECT)
{
    MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    ExitApp
}

Loop ; Wait for incomming connections
{
; accept requests that are in the pipeline of the socket   
   conectioncheck := 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 > 1
    {
       MsgBox Incoming connection accepted
       break   
   }
    sleep 500 ; wait half 1 second then accept again
}   
return

SendviaNet:
Gui, Submit, NoHide
SendData(conectioncheck,SendText)
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. 
}



ReceiveData(wParam, lParam)
; By means of OnMessage(), this function has been set up to be called automatically whenever new data
; arrives on the connection. 
{
   global ShowRecieved
    socket := wParam
    ReceivedDataSize = 4096  ; Large in case a lot of data gets buffered due to delay in processing previous data.
    Loop  ; This loop solves the issue of the notification message being discarded due to thread-already-running.
    {
        VarSetCapacity(ReceivedData, ReceivedDataSize, 0)  ; 0 for last param terminates string for use with recv().
        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".
                return 1
            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.
        }
        ; Otherwise, process the data received.
        Loop, parse, ReceivedData, `n, `r
        {
           ShowRecieved = %ShowRecieved%%A_LoopField%
           Tooltip % ShowRecieved
        }
    }
    return 1  ; Tell the program that no further processing of this message is needed.
}

SendData(wParam,SendData)
{
socket := wParam
;MsgBox %socket%  %SendData%
SendDataSize := VarSetCapacity(SendData)
SendDataSize += 1
sendret := DllCall("Ws2_32\send", "UInt", socket, "Str", SendData, "Int", SendDatasize, "Int", 0)
;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)
}



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, Edit, w100 vSendText
Gui, Add, Button, gSendviaNet, Send
Gui, Add, Button, gConnection_Init, Connect
Gui, Show

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

SendviaNet:
Gui, Submit, NoHide
SendData(socket,SendText)
SentText =
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. 
{
   global ShowRecieved
    socket := wParam
    ReceivedDataSize = 4096  ; Large in case a lot of data gets buffered due to delay in processing previous data.
    Loop  ; This loop solves the issue of the notification message being discarded due to thread-already-running.
    {
        VarSetCapacity(ReceivedData, ReceivedDataSize, 0)  ; 0 for last param terminates string for use with recv().
        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".
                return 1
            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.
        }
        ; Otherwise, process the data received.
        Loop, parse, ReceivedData, `n, `r
        {
            ShowRecieved = %ShowRecieved%%A_LoopField%
           Tooltip % ShowRecieved
        }
    }
    return 1  ; Tell the program that no further processing of this message is needed.
}

SendData(wParam,SendData)
{
socket := wParam
;MsgBox %socket%  %SendData%
SendDataSize := VarSetCapacity(SendData)
SendDataSize += 1
sendret := DllCall("Ws2_32\send", "UInt", socket, "Str", SendData, "Int", SendDatasize, "Int", 0)
;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)
}



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
[/b]
_________________
1) All my code can be reused in ANY way. 2) Please check the help and the forum-search, before posting questions; the answer is out there...


Last edited by Zed Gecko on Sat May 10, 2008 6:58 am; edited 2 times in total
Back to top
View user's profile Send private message
BoBo
Guest





PostPosted: Thu Nov 02, 2006 4:38 pm    Post subject: Reply with quote

GOSH! Das nenn ich beeindruckend Shocked Thx/Danke. Very Happy
Back to top
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Thu Nov 02, 2006 4:54 pm    Post subject: Reply with quote

Wow! I didn't looked the code, but this sure have been asked many times!
If it works with both client and server on same computer, it can even be used for inter-script communication...
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
Zed Gecko



Joined: 23 Sep 2006
Posts: 98

PostPosted: Thu Nov 02, 2006 5:39 pm    Post subject: Reply with quote

Yeah, and it was so close ^^

And it works with both client and server on the same computer.
Back to top
View user's profile Send private message
kiu



Joined: 18 Dec 2005
Posts: 229
Location: Italy - Galatro(RC)

PostPosted: Fri Nov 03, 2006 12:28 am    Post subject: Reply with quote

very impressive
_________________
____________________
______________________
kiu
Back to top
View user's profile Send private message Visit poster's website
qtmspin



Joined: 17 Oct 2006
Posts: 22

PostPosted: Fri Nov 03, 2006 12:43 am    Post subject: Reply with quote

Can you guide me in what changes need to be made to allow more then one connection to the server.

I would like multple client to connect to the server. When the server sends a message, I would like it sent to all clients.

When I connect a 2nd client to the server I get the error: connect() indicated Winsock error 0?

-which is funny because 0 means no error right?

Great work,
Matt
Back to top
View user's profile Send private message
Zed Gecko



Joined: 23 Sep 2006
Posts: 98

PostPosted: Fri Nov 03, 2006 9:43 am    Post subject: Reply with quote

First of all i want to state that iīm a noob to this, so this may be (partially) wrong and i might use wrong words.

To make a Server for more than one connection,
you should seperate the operations for the different sockets,
because right now the script does this:

1. the server initalizes the winsock with
Code:
WSAStartup


2. the creates a socket (the first socket of two) with
Code:
socket


3. the server binds itself to the socket and tells the
socket that it is listening with
Code:
bind
listen


4. the server tells the socket to send WindowsMessages on Received Data
(this is optional, because you can just question the socket with a
looped receive instead) with
Code:
WSAAsyncSelect


5. the server accepts an incoming connection blind
(without knowing if there really one) in a loop
until it returnes a valid socket ID with
Code:
accept

if accept returns a valid socket id, it means that
there realy was an incomming connection, that could be accepted, and
winsock has automacaly created a new socket with the
same properties as the first socket
(not only same type and ip, but also
if it is sending Windows Messages when WSAAsyncSelect was called)
[My Loop stopps after one accepted connection]

6. the server sends and receives data through the new socket with
Code:
send
recv

The send and receive command have to work with the new socket,
that was created by winsock, because the incoming connection will
talk to this socket and not the one that was monitoring for the incoming connection.

To handle more than one connection you will first have make the
accept loop (Nr.6)keep going after the first accepted connection.
You will hopefully get a socket for each incoming connection.

The tricky part will be to handle all the sockets. The MSDN recommends
to start a new thread for each socket.
(That would probably mean to start
another script with the socket id as commandline parameter,
or using WindowsMessages for the transfer of the socket id.
The new script will maybe need to init Winsock itself, but i donīt know?

If you only have limited demands, you can also use the function
that is called by the WindowsMessages received from the socket,
to not only receive but also send some data, but iīm not shure if there
will be "collision" problems.

Or you donīt tell the winsock to send WindowsMessages at all(Nr.4),
and question and respond to all the open sockets
one after another in a loop.
Back to top
View user's profile Send private message
majkinetor



Joined: 24 May 2006
Posts: 3615
Location: Belgrade

PostPosted: Fri Nov 03, 2006 9:52 am    Post subject: Reply with quote

beutiful
_________________
Back to top
View user's profile Send private message MSN Messenger
robiandi



Joined: 08 Aug 2006
Posts: 50

PostPosted: Fri Nov 03, 2006 3:00 pm    Post subject: Reply with quote

copy - paste - network adresses specified - run without error <== great, Zed Gecko
Back to top
View user's profile Send private message
qtmspin



Joined: 17 Oct 2006
Posts: 22

PostPosted: Tue Nov 07, 2006 6:33 pm    Post subject: Reply with quote

Here is my ~solution~ to sending one message to multiple clients.


I changed this
Code:
Loop ; Wait for incomming connections
{
; accept requests that are in the pipeline of the socket   
   conectioncheck := 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 > 1
    {
       MsgBox Incoming connection accepted
       break   
   }
    sleep 500 ; wait half 1 second then accept again
}   
return


to this...
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


and updated send via net to this...
Code:
SendviaNet:
Gui, Submit, NoHide
Loop %i% {
   SendData(conectioncheck%A_Index%,SendText)
}
SentText =
return


I know, I know... but it works!
Back to top
View user's profile Send private message
Zed Gecko



Joined: 23 Sep 2006
Posts: 98

PostPosted: Mon Nov 13, 2006 7:19 pm    Post subject: Reply with quote

Quote:
Your script is working beautifully. It's very fast. < 10 ms, I have a small problem, when I close any of the connected clients, it kills the server also. Any idea why this is and how I can stop it?


This is the default behaivour from the WinLirc Script, which i didnīt change,
also the server will kill the clients.

to change this, in the serverscript you got to get rid of these lines:
Code:

if ReceivedDataLength = 0  ; The connection was gracefully closed,
   ExitApp  ; The OnExit routine will call WSACleanup() for us.

in the ReciverData function.

and you better change the WindowsMessages the socket sends
from
Code:
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CLOSE|FD_CONNECT)

to
Code:

if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT)


and you better create a new WindowsMessage Handler for the FD_CLOSE Message, like:
Code:

NotificationMsg2 = 0x6666
OnMessage(NotificationMsg2, "ConnectionClosed")

Code:

if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg2, "Int", FD_CLOSE)

Code:

ConnectionClosed(wParam, lParam)
{
}



but this is all guessing, so please try out and report in forum please.
Back to top
View user's profile Send private message
HappyFlyer
Guest





PostPosted: Tue Nov 14, 2006 3:28 pm    Post subject: like key2Lan Reply with quote

Can this code be changed so i can send keystrokes just like i am on the other PC? (1 server 3 clients?)

just like key2lan does ?

http://www.wideview.it/key2lan.htm

Flyer
Back to top
Zed Gecko



Joined: 23 Sep 2006
Posts: 98

PostPosted: Tue Nov 14, 2006 6:47 pm    Post subject: Reply with quote

Well, since autohotkey can send Keystrokes, using "send" and other commands. It is possible to send Keystrokes over the net with this script.
Just exchange the "Tooltip" command with a "send" command for a start
Back to top
View user's profile Send private message
qtmspin



Joined: 17 Oct 2006
Posts: 22

PostPosted: Tue Nov 14, 2006 7:07 pm    Post subject: problem solved Reply with quote

Thanks Zed. Taking out the FD_CLOSE was enough to stop the client from closing the server. For my purposes (only 3 users) that was enough. I am ok with the server killing the clients because its good to know that they need to be reconnected. Thank you for the hardwork and ongoing support.

Matt
Back to top
View user's profile Send private message
Happyflyer
Guest





PostPosted: Wed Nov 15, 2006 8:25 am    Post subject: Reply with quote

Zed Gecko wrote:
Well, since autohotkey can send Keystrokes, using "send" and other commands. It is possible to send Keystrokes over the net with this script.
Just exchange the "Tooltip" command with a "send" command for a start


Great !!!!

Now I need to change this script for my FS.

Thanks a lot Zed !!!
Back to top
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3, 4, 5, 6, 7  Next
Page 1 of 7

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group