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 

TCP/IP evolved

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
STEPHANVS



Joined: 03 Mar 2007
Posts: 14
Location: Cluj-Napoca

PostPosted: Thu Jun 21, 2007 1:06 pm    Post subject: TCP/IP evolved Reply with quote

Hi. I used Zed Gecko's TCP/IP scritps, and modified them a little, so the server can accept multiple connections. Well it works until i want the server to accept something that a client sends.

In this case the server broadcasts the current time to all clients. I am using a STRING variable to store the client's sockets... I've tried everything I know to get it working. Please help.

Server
Code:
#SingleInstance Force
Network_Address = 127.0.0.1
Network_Port = 9000

NewData := false
DataReceived =

Gui, Add, Text, vReceivedText w70, 00:00:00
GuiControl, +Center, ReceivedText
Gui -MaximizeBox -MinimizeBox
Gui, Show, x10 y10, Server

Gosub Connection_Init

SetTimer, ReceiveProcedure, 500
SetTimer, SendProcedure, 1000

return

Connection_Init:
OnExit, ExitSub

socket := PrepareForIncomingConnection(Network_Address, Network_Port)
if socket = -1
    ExitApp

Process, Exist
DetectHiddenWindows On
ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel)
DetectHiddenWindows Off

NotificationMsg = 0x5555
OnMessage(NotificationMsg, "ReceiveData")

ExitMsg = 0x5556
OnMessage(ExitMsg, "ExitData")

FD_READ = 1
FD_CLOSE = 32
FD_CONNECT = 20
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT) OR DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", ExitMsg, "Int", FD_CLOSE)
{
    MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
    ExitApp
}

SetTimer, NewConnectionCheck, 500
return

PrepareForIncomingConnection(IPAddress, Port)
{
    VarSetCapacity(wsaData, 32)
    result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData)
    if ErrorLevel
    {
        MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
        return -1
    }
    if result
    {
        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
    }
    SizeOfSocketAddress = 16
    VarSetCapacity(SocketAddress, SizeOfSocketAddress)
    InsertInteger(2, SocketAddress, 0, AF_INET)
    InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)
    InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)
    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
}

ReceiveData(wParam, lParam)
{
    global DataReceived
    global NewData
    global ConnectionList
    socket := wParam
    ReceivedDataSize = 4096
    Loop
    {
        VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
        ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
        if ReceivedDataLength = 0
            StringReplace, ConnectionList, ConnectionList, %socket%`n
            DllCall("Ws2_32\closesocket", "UInt", socket)
        if ReceivedDataLength = -1
        {
            WinsockError := DllCall("Ws2_32\WSAGetLastError")
            if WinsockError = 10035
            {
                DataReceived = %TempDataReceived%
                NewData := true
                return 1
            }
            if WinsockError <> 10054
            {
                MsgBox % "recv() indicated Winsock error " . WinsockError
                StringReplace, ConnectionList, ConnectionList, %socket%`n
                DllCall("Ws2_32\closesocket", "UInt", socket)
            }
        }
        if (A_Index = 1)
            TempDataReceived =
        TempDataReceived = %TempDataReceived%%ReceivedData%
    }
    return 1
}

ExitData(wParam, lParam)
{
    global ConnectionList
    socket := wParam
    ReceivedDataSize = 16
    VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
    ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
    StringReplace, ConnectionList, ConnectionList, %socket%`n
    DllCall("Ws2_32\closesocket", "UInt", socket)
    return 1
}

SendData(wParam,SendData)
{
    SendDataSize := VarSetCapacity(SendData)
    SendDataSize += 1
    Loop, parse, wParam, `n
    {
        If A_LoopField =
            Continue
        socket := A_LoopField
        sendret := DllCall("Ws2_32\send", "UInt", socket, "Str", SendData, "Int", SendDatasize, "Int", 0)
    }
}


InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
    Loop %pSize%
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

NewConnectionCheck:
ConnectionCheck := DllCall("Ws2_32\accept", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
if ConnectionCheck > 1
    ConnectionList = %ConnectionList%%ConnectionCheck%`n
Return

SendProcedure:
If ConnectionList <>
{
    SendText = %A_Hour%:%A_Min%:%A_Sec%
    SendData(ConnectionList,SendText)
}
Return

ReceiveProcedure:
    if NewData
        GuiControl, , ReceivedText, %DataReceived%
    NewData := false
Return

GuiClose:
ExitSub:
DllCall("Ws2_32\WSACleanup")
ExitApp

^!m::MsgBox %ConnectionList%


Client
Code:
#SingleInstance OFF
Network_Address = 127.0.0.1
Network_Port = 9000

NewData := false
DataReceived =

Gui, Add, Text, vReceivedText w70, 00:00:00
GuiControl, +Center, ReceivedText
Gui -MaximizeBox -MinimizeBox
Gui, Show, x10 y100, Client

GoSub, Connection_Init

;SendData(socket,SendText)

SetTimer, SendProcedure, 1000
SetTimer, ReceiveProcedure, 500

return

Connection_Init:
OnExit, ExitSub

socket := ConnectToAddress(Network_Address, Network_Port)
if socket = -1
    ExitApp

Process, Exist
DetectHiddenWindows On
ScriptMainWindowId := WinExist("ahk_class AutoHotkey ahk_pid " . ErrorLevel)
DetectHiddenWindows Off

NotificationMsg = 0x5556
OnMessage(NotificationMsg, "ReceiveData")

FD_READ = 1
FD_CLOSE = 32
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


ConnectToAddress(IPAddress, Port)
{
    VarSetCapacity(wsaData, 32)
    result := DllCall("Ws2_32\WSAStartup", "UShort", 0x0002, "UInt", &wsaData)
    if ErrorLevel
    {
        MsgBox WSAStartup() could not be called due to error %ErrorLevel%. Winsock 2.0 or higher is required.
        return -1
    }
    if result
    {
        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
    }
    SizeOfSocketAddress = 16
    VarSetCapacity(SocketAddress, SizeOfSocketAddress)
    InsertInteger(2, SocketAddress, 0, AF_INET)
    InsertInteger(DllCall("Ws2_32\htons", "UShort", Port), SocketAddress, 2, 2)
    InsertInteger(DllCall("Ws2_32\inet_addr", "Str", IPAddress), SocketAddress, 4, 4)
    if DllCall("Ws2_32\connect", "UInt", socket, "UInt", &SocketAddress, "Int", SizeOfSocketAddress)
    {
        MsgBox % "connect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError") . "?"
        return -1
    }
    return socket
}

ReceiveData(wParam, lParam)
{
    global DataReceived
    global NewData
    socket := wParam
    ReceivedDataSize = 4096
    Loop
    {
        VarSetCapacity(ReceivedData, ReceivedDataSize, 0)
        ReceivedDataLength := DllCall("Ws2_32\recv", "UInt", socket, "Str", ReceivedData, "Int", ReceivedDataSize, "Int", 0)
        if ReceivedDataLength = 0
            ExitApp
        if ReceivedDataLength = -1
        {
            WinsockError := DllCall("Ws2_32\WSAGetLastError")
            if WinsockError = 10035
            {
                DataReceived = %TempDataReceived%
                NewData := true
                return 1
            }
            if WinsockError <> 10054
                MsgBox % "recv() indicated Winsock error " . WinsockError
            ExitApp
        }
        if (A_Index = 1)
            TempDataReceived =
        TempDataReceived = %TempDataReceived%%ReceivedData%
    }
    return 1
}

SendData(wParam,SendData)
{
    socket := wParam
    SendDataSize := VarSetCapacity(SendData)
    SendDataSize += 1
    sendret := DllCall("Ws2_32\send", "UInt", socket, "Str", SendData, "Int", SendDatasize, "Int", 0)
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
{
    Loop %pSize%
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

ReceiveProcedure:
    if NewData
        GuiControl, , ReceivedText, %DataReceived%
    NewData := false
Return

SendProcedure:
SendText = %A_Hour%:%A_Min%:%A_Sec%
SendData(socket,SendText)
Return

GuiClose:
ExitSub:
DllCall("Ws2_32\WSACleanup")
ExitApp
Back to top
View user's profile Send private message
STEPHANVS



Joined: 03 Mar 2007
Posts: 14
Location: Cluj-Napoca

PostPosted: Fri Jun 22, 2007 6:18 pm    Post subject: Reply with quote

Sad No answer... should i post the code with explanations?
Back to top
View user's profile Send private message
Ian
Guest





PostPosted: Sat Jun 23, 2007 11:53 pm    Post subject: Reply with quote

I am interested too in solving this.

The ReceiveData routine at the server is not called. I have tried to change the WSAAsyncSelect line commenting the OR option and after that, ReceiveData is called but a socket error raises.
Back to top
Ian
Guest





PostPosted: Sun Jun 24, 2007 8:08 am    Post subject: Reply with quote

Hi again,

it works with this:


DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", ExitMsg, "Int", FD_CLOSE)
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT)
{
...
}

and this in ReceiveData() routine:
if ReceivedDataLength = 0
{
StringReplace, ConnectionList, ConnectionList, %socket%`n
DllCall("Ws2_32\closesocket", "UInt", socket)
}

The socket error was that closesocket was called even when ReceivedDataLength was different to 0.

About the If, probably is something about logic operator short-circuiting the evaluation of both calls, if someone knows a clear solution for that...
Back to top
STEPHANVS



Joined: 03 Mar 2007
Posts: 14
Location: Cluj-Napoca

PostPosted: Mon Jun 25, 2007 3:10 pm    Post subject: Reply with quote

Cool, man Cool i missed the ReceiveData's {}'s... Works fine now, thanks again!
Back to top
View user's profile Send private message
STEPHANVS



Joined: 03 Mar 2007
Posts: 14
Location: Cluj-Napoca

PostPosted: Mon Jun 25, 2007 4:37 pm    Post subject: Reply with quote

... although this way the server doesn't close the socket on client exit ... Question

The problem is
Code:
DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", ExitMsg, "Int", FD_CLOSE)
is getting offline when
Code:
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT)
{
...
}

is called...
Back to top
View user's profile Send private message
tinku99



Joined: 03 Aug 2007
Posts: 35

PostPosted: Mon Aug 04, 2008 10:59 pm    Post subject: closing sockets Reply with quote

try this:
if DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", NotificationMsg, "Int", FD_READ|FD_CONNECT)
{
MsgBox % "WSAAsyncSelect() indicated Winsock error " . DllCall("Ws2_32\WSAGetLastError")
DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", ExitMsg, "Int", FD_CLOSE)
ExitApp
}
else
DllCall("Ws2_32\WSAAsyncSelect", "UInt", socket, "UInt", ScriptMainWindowId, "UInt", ExitMsg, "Int", FD_CLOSE)

this way that dllcall always happens
Back to top
View user's profile Send private message
PixelVision



Joined: 28 Jun 2008
Posts: 4
Location: NIECE, FRANCE

PostPosted: Thu Aug 07, 2008 2:40 am    Post subject: Reply with quote

Greetings -- Can the SERVER SIDE ONLY script be modified with the additions of

Code:


Add, Button,,CONNECT
Add, Button,,DISCONNECT



Very Happy Please help!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
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