thqby / ahk2_lib

MIT License
197 stars 26 forks source link

Minimal working example for Socket.Ahk #27

Closed EstZw3i closed 11 months ago

EstZw3i commented 11 months ago

Hi, I'm trying to work with Socket.ahk via named pipes for existing compatibility with my existing codebase but I have trouble setting it up. I'm unfamiliar with socket technology so there's that as well.

From my limited understanding of the source code. I have set up something like this

Server

class TestServer extends Socket.Server {
    onREAD(wp){
        MsgBox "On Read"    
    }
    onCONNECT(wp){
        MsgBox "On Connect"
    }
}

server := TestServer(,"\\.\pipe\testPipe")

Client

class TestClient extends Socket.Client {
    onREAD(data) {
        MsgBox("Client Read")
    }
    onWRITE(data){
        MsgBox "Client Write"
    }
}

tClient := TestClient("\\.\pipe\testPipe")
tClient.SendText("hi")

I assume that the server opens up the socket for listening via TestServer(,"\\.\pipe\testPipe") while the client connects to this listening port via TestClient("\\.\pipe\testPipe"). I'm definitely missing something here as this clearly doesn't work. It would be great if you could provide a minimal working example for both Server and Client classes so I know what the initial setup looks like.

I also happen to stumble across this AHK forum post but the code looks to be tailored towards communicating with LSP server which isn't my use case. I also notice the method static Call(path?, port := 1219) and the implementation doesn't seem to align with what I understood as it creates a server socket rather than a client socket.

thqby commented 11 months ago
#Include <Socket>
class TestServer extends Socket.Server {
    onACCEPT(err) {
        this.client := this.AcceptAsClient()
        this.client.onREAD := onread
        onread(this, err) {
            MsgBox("receive from client`n" this.RecvText())
            this.SendText('hello')
        }
    }
}

server := TestServer(, "\\.\pipe\testPipe")

class TestClient extends Socket.Client {
    onREAD(err) {
        MsgBox("receive from server`n" this.RecvText())
    }
}
Persistent
tClient := TestClient("\\.\pipe\testPipe")
tClient.SendText("hi")

The server can establish connections with multiple clients, so when the client requests a connection, it needs to accept a connection and create a new socket to contact the client.

I also happen to stumble across this AHK forum post but the code looks to be tailored towards communicating with LSP server which isn't my use case.

I tried to connect to the LSP server through the named pipe, but couldn't establish a connection to the nodejs end, while there was no problem between ahk.

EstZw3i commented 11 months ago

Thank you for your time and the quick response. I got it working on my side too.

This particular line of code (this.client.onREAD := onread) looks a bit odd to read for me personally but I guess it implements an event handler on the client socket whenever the clients sends something? I do have additional questions if you don't mind the length

1. How do I close the socket for the following scenarios

1. Disconnecting the socket Client side after connection
2. Forcefully disconnecting the client from server side
3. Closing the server socket 

I assume I should just remove the reference/pointer to those sockets and the corresponding __Delete method will be called accordingly for disposal?

2. Does this library fully allow asynchronous event handling

Normal Named Pipe servers with DLL call to ConnectNamedPipe will block the execution of the rest of the code and this proves to be a problem since I have a GUI running in my AHK application. I plan to fully refactor my codebase from using named pipes to socket depending on which is easier to maintain.

3. What are the relevant Events that I should handle for Server/Client in Named pipes or Pure Socket(in the future)

I assume only these are relevant for now? I'm only communicating via stringified JSON data between server and client

  1. Client : onREAD
  2. server : onACCEPT
  3. Accepted client : onREAD

4. My Codebase isn't really communicating between 2 AHK Applications but AHK <-> C# so my solution is something like this

1. AHK -> C#, using Named Pipes
2. C# -> AHK, using WM_COPYDATA 

I would rather have both side use the same method of communication but setting up named pipe server on AHK proves to be tricky as what I mentioned on #2. I haven't tried using this library to talk with my C# named pipe server yet so that's something I'll try later on.

This is a bit out of scope but if I want to implement the socket on C# I guess this should be the class I'm working with? No worries if you are unsure about it as I'll try it out myself once I get things setup on AHK.

Are there any other platforms that I could contact you since opening an issue for questions is a bit strange to me.

thqby commented 11 months ago

1. How do I close the socket for the following scenarios

I assume I should just remove the reference/pointer to those sockets and the corresponding __Delete method will be called accordingly for disposal?

Yes, or call __Delete method to close. If there is an onclose method, it will be triggered when the other end is disconnected.

2. Does this library fully allow asynchronous event handling

To implement any event, enable asynchronous mode, otherwise it is synchronous mode. If the onconnect method is not implemented, the connection is synchronously blocked.

3. What are the relevant Events that I should handle for Server/Client in Named pipes or Pure Socket(in the future)

I assume only these are relevant for now? I'm only communicating via stringified JSON data between server and client

Depending on the requirements, onread and onclose are generally implemented, and the server also needs to implement onaccept.

Are there any other platforms that I could contact you since opening an issue for questions is a bit strange to me.

autohotkey.com But I didn't publish a special topic for the library

EstZw3i commented 11 months ago

Alright, big thanks for the help.

skygate2012 commented 10 months ago

But I didn't publish a special topic for the library

You should publish one! I struggled to get the library working until seeing your example.