 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
STEPHANVS
Joined: 03 Mar 2007 Posts: 14 Location: Cluj-Napoca
|
Posted: Thu Jun 21, 2007 1:06 pm Post subject: TCP/IP evolved |
|
|
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 |
|
 |
STEPHANVS
Joined: 03 Mar 2007 Posts: 14 Location: Cluj-Napoca
|
Posted: Fri Jun 22, 2007 6:18 pm Post subject: |
|
|
No answer... should i post the code with explanations? |
|
| Back to top |
|
 |
Ian Guest
|
Posted: Sat Jun 23, 2007 11:53 pm Post subject: |
|
|
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
|
Posted: Sun Jun 24, 2007 8:08 am Post subject: |
|
|
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
|
Posted: Mon Jun 25, 2007 3:10 pm Post subject: |
|
|
Cool, man i missed the ReceiveData's {}'s... Works fine now, thanks again! |
|
| Back to top |
|
 |
STEPHANVS
Joined: 03 Mar 2007 Posts: 14 Location: Cluj-Napoca
|
Posted: Mon Jun 25, 2007 4:37 pm Post subject: |
|
|
... although this way the server doesn't close the socket on client exit ...
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 |
|
 |
tinku99
Joined: 03 Aug 2007 Posts: 35
|
Posted: Mon Aug 04, 2008 10:59 pm Post subject: closing sockets |
|
|
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 |
|
 |
PixelVision
Joined: 28 Jun 2008 Posts: 4 Location: NIECE, FRANCE
|
Posted: Thu Aug 07, 2008 2:40 am Post subject: |
|
|
Greetings -- Can the SERVER SIDE ONLY script be modified with the additions of
| Code: |
Add, Button,,CONNECT
Add, Button,,DISCONNECT
|
Please help! |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|