 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Lexikos
Joined: 17 Oct 2006 Posts: 2602 Location: Australia, Qld
|
Posted: Mon Mar 31, 2008 10:24 pm Post subject: |
|
|
| 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; |
|
|
| Back to top |
|
 |
IsNull
Joined: 10 May 2007 Posts: 72 Location: .switzerland
|
|
| Back to top |
|
 |
LYCOS17
Joined: 06 Feb 2008 Posts: 20 Location: Dallas
|
Posted: Mon Apr 21, 2008 2:04 am Post subject: |
|
|
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! 
Last edited by LYCOS17 on Thu May 01, 2008 10:22 am; edited 4 times in total |
|
| Back to top |
|
 |
LYCOS17
Joined: 06 Feb 2008 Posts: 20 Location: Dallas
|
Posted: Wed Apr 30, 2008 3:48 pm Post subject: |
|
|
*bump*
Last edited by LYCOS17 on Thu May 01, 2008 10:17 am; edited 1 time in total |
|
| Back to top |
|
 |
Z Gecko Guest
|
Posted: Wed Apr 30, 2008 8:03 pm Post subject: |
|
|
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. |
|
| Back to top |
|
 |
CraSH23000
Joined: 22 Jun 2007 Posts: 38
|
Posted: Wed Apr 30, 2008 9:09 pm Post subject: |
|
|
Thanks a lot for this Zed Gecko, this looks awesome, and thanks LYCOS17 for bumping because I would have never seen this, lol. _________________ What is real in our infinitely alternating perception of reality? |
|
| Back to top |
|
 |
CraSH23000
Joined: 22 Jun 2007 Posts: 38
|
Posted: Fri May 02, 2008 6:35 am Post subject: |
|
|
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:
(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 _________________ What is real in our infinitely alternating perception of reality? |
|
| Back to top |
|
 |
Z Gecko Guest
|
Posted: Fri May 02, 2008 7:08 am Post subject: |
|
|
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? |
|
| Back to top |
|
 |
CraSH23000
Joined: 22 Jun 2007 Posts: 38
|
Posted: Fri May 02, 2008 7:43 am Post subject: |
|
|
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. _________________ What is real in our infinitely alternating perception of reality? |
|
| Back to top |
|
 |
Z Gecko Guest
|
Posted: Fri May 02, 2008 8:22 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
CraSH23000
Joined: 22 Jun 2007 Posts: 38
|
Posted: Fri May 02, 2008 8:54 am Post subject: |
|
|
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. _________________ What is real in our infinitely alternating perception of reality? |
|
| Back to top |
|
 |
Burn2 Guest
|
Posted: Sat May 03, 2008 1:06 pm Post subject: |
|
|
Hi,
Is it possible to create username and password checker at server side that received from client? |
|
| Back to top |
|
 |
Z Gecko Guest
|
Posted: Sat May 03, 2008 1:32 pm Post subject: |
|
|
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.  |
|
| Back to top |
|
 |
FredMcGary Guest
|
Posted: Wed May 14, 2008 6:06 am Post subject: |
|
|
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. |
|
| Back to top |
|
 |
Zed Gecko
Joined: 23 Sep 2006 Posts: 98
|
Posted: Mon May 19, 2008 6:10 am Post subject: |
|
|
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 _________________ 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... |
|
| 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
|