Yet another winsock class (TCP/IPv4, Text only)

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
MiM
Posts: 61
Joined: 20 Apr 2021, 04:31

Yet another winsock class (TCP/IPv4, Text only)

11 Feb 2024, 10:54


This class is based on Socket.ahk so big thanks to @geek!
Also thanks to:
@TheArkive for general winsock help and testing/troubleshooting with me
@anonymous1184 mostly for help relating to how classes work

Template/Example:

Code: Select all

#SingleInstance, Off
SetBatchLines, -1

ListeningPort := "8338"
ConnectingAddress := A_IPAddress1, ConnectingPort := "8338"

; try { ; Get own public ip address (can use this for connecting instead of A_IPAddress1/2/3/4 when listening on 0.0.0.0)
;   HttpObj := ComObjCreate("WinHttp.WinHttpRequest.5.1"), HttpObj.SetTimeouts(0, 1000, 1000, 1000)
;   HttpObj.Open("GET", "http://www.netikus.net/show_ip.html"), HttpObj.Send(), ConnectingAddress := HttpObj.ResponseText
; }

Gui, -DPIScale
Gui, Margin, 0, 0
;──────────────────────────────────────────────────────────────── Server ─────────────────────────────────────────────────────────────────┐
Gui, Font, s11, Consolas
Gui, Add, GroupBox, x10 y10 w401 h520 cRed +Center +hwndFocusDummy, Server

; Listen
Gui, Font, s8
Gui, Add, GroupBox, x17 y26 w72 h69
Gui, Font, s11
Gui, Add, Edit, xp+5 yp+12 wp-10 h22 +hwndServerPortEditHwnd +Center +Number +Limit5 -Multi -VScroll, % ListeningPort
DllCall("SendMessage", "Ptr", ServerPortEditHwnd, "UInt", 0x1501, "Ptr", 1, "WStr", "Port")
Gui, Font, s10
Gui, Add, Button, xp-1 yp+24 wp+2 h28 gServerListen, Listen

; Disconnect
Gui, Font, s8
Gui, Add, GroupBox, x88 y26 w102 h69
Gui, Font, s11
Gui, Add, Edit, xp+5 yp+12 w92 h22 +hwndServerDisconnectEditHwnd +Center +Number +Limit5 -Multi -VScroll
DllCall("SendMessage", "Ptr", ServerDisconnectEditHwnd, "UInt", 0x1501, "Ptr", 1, "WStr", "Socket")
Gui, Font, s10
Gui, Add, Button, xp-1 yp+24 w94 h28 gServerDisconnect, Disconnect

; Send
Gui, Font, s8
Gui, Add, GroupBox, x189 y26 w214 h69 +Center
Gui, Font, s11
Gui, Add, Edit, xp+5 yp+12 wp-10 h22 +hwndServerSendTextEditHwnd +Center +Limit -Multi -VScroll, SomeText
DllCall("SendMessage", "Ptr", ServerSendTextEditHwnd, "UInt", 0x1501, "Ptr", 1, "WStr", "Text to send")
Gui, Font, s12
Gui, Add, Edit, xp yp+25 w70 h26 +hwndServerSendSocketEditHwnd +Center +Limit +Limit5 -Multi -VScroll
DllCall("SendMessage", "Ptr", ServerSendSocketEditHwnd, "UInt", 0x1501, "Ptr", 1, "WStr", "Socket")
Gui, Font, s11
Gui, Add, Button, xp+72 yp-1 w133 h28 gServerSend, Send

; Log
Gui, Font, s8
Gui, Add, Text, x20 y110 w380 +BackgroundTrans +Center, SERVER LOG
Gui, Add, Progress, xp-3 yp-3 wp+6 hp+6 +hwndServerLogTextHwnd +cCCCCCC +BackgroundA0A0A0, 100
WinSet, Top,, ahk_id %ServerLogTextHwnd%
Gui, Add, GroupBox, xp yp+11 wp+1 h405 cBlack
Gui, Add, Edit, xp+1 yp+10 wp-5 hp-15 +hwndServerLogHwnd +ReadOnly -Theme -E0x200
;─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

;──────────────────────────────────────────────────────────────── Client ─────────────────────────────────────────────────────────────────┐
Gui, Font, s11
Gui, Add, GroupBox, x420 y10 w401 h520 cBlue +Center, Client

; Connect/Disconnect
Gui, Font, s8
Gui, Add, GroupBox, x427 y26 w218 h69 +Center
Gui, Font, s11
Gui, Add, Edit, xp+5 yp+12 wp-10 h22 +hwndClientAddressEditHwnd +Center +Limit -Multi -VScroll, % ConnectingAddress
DllCall("SendMessage", "Ptr", ClientAddressEditHwnd, "UInt", 0x1501, "Ptr", 1, "WStr", "Address")
Gui, Font, s12
Gui, Add, Edit, xp yp+25 w54 h26 +hwndClientPortEditHwnd +Center +Number +Limit5 -Multi -VScroll, % ConnectingPort
DllCall("SendMessage", "Ptr", ClientPortEditHwnd, "UInt", 0x1501, "Ptr", 1, "WStr", "Port")
Gui, Font, s10
Gui, Add, Button, xp+56 yp-1 w66 h28 gClientConnect, Connect
Gui, Add, Button, xp+67 yp w86 h28 gClientDisconnect, Disconnect

; Send
Gui, Font, s8
Gui, Add, GroupBox, x644 y26 w169 h69 +Center
Gui, Font, s11
Gui, Add, Edit, xp+5 yp+12 wp-10 h22 +hwndClientSendEditHwnd +Limit +Center -Multi -VScroll, SomeText
DllCall("SendMessage", "Ptr", ClientSendEditHwnd, "UInt", 0x1501, "Ptr", 1, "WStr", "Text to send")
Gui, Add, Button, xp-1 yp+24 wp+2 h28 gClientSend, Send

; Log
Gui, Font, s8
Gui, Add, Text, x430 y110 w380 +BackgroundTrans +Center, CLIENT LOG
Gui, Add, Progress, xp-3 yp-3 wp+6 hp+6 +hwndClientLogTextHwnd +cCCCCCC +BackgroundA0A0A0, 100
WinSet, Top,, ahk_id %ClientLogTextHwnd%
Gui, Add, GroupBox, xp yp+11 wp+1 h405 cBlack
Gui, Add, Edit, xp+1 yp+10 wp-5 hp-15 +hwndClientLogHwnd +ReadOnly -Theme -E0x200
;─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
GuiControl, Focus, %FocusDummy%
Gui, Show, x0 y0 w830 h539
Return
GuiEscape:
GuiClose:
ExitApp

ServerListen:
if !(Server)
  Server := new Winsock("Server", "SocketHandler")
GuiControlGet, ServerPort,, % ServerPortEditHwnd
Server.Listen("0.0.0.0", ServerPort)
Return

ServerDisconnect:
GuiControlGet, ServerDisconnectText,, % ServerDisconnectEditHwnd
Server.Disconnect(ServerDisconnectText)
Return

ServerSend:
GuiControlGet, ServerSendText,, % ServerSendTextEditHwnd
GuiControlGet, ServerSendSocket,, % ServerSendSocketEditHwnd
if (ServerSendSocket)
  Server.Send(ServerSendSocket, ServerSendText)
else
  Server.Send(ServerSendText)
Return

ClientConnect:
if !(Client)
  Client := new Winsock("Client", "SocketHandler")
GuiControlGet, ClientAddress,, % ClientAddressEditHwnd
GuiControlGet, ClientPort,, % ClientPortEditHwnd
Client.Connect(ClientAddress, ClientPort)
Return

ClientDisconnect:
Client.Disconnect()
Return

ClientSend:
GuiControlGet, ClientSendText,, % ClientSendEditHwnd
Client.Send(ClientSendText)
Return

SocketHandler(SocketName, Event, EventInfo) {
  Global ServerLogHwnd, ClientLogHwnd
  if (SocketName = "Server") {
    Switch (Event) {
      Case "Listening": GuiPrint(ServerLogHwnd, "Listening on """ EventInfo.Address ":" EventInfo.Port """")
      Case  "Accepted": GuiPrint(ServerLogHwnd, "Accepted client """ EventInfo.SocketNumber " | " EventInfo.SocketAddress """")
      Case  "Received": GuiPrint(ServerLogHwnd, "Received """ EventInfo.Message """ from client """ EventInfo.SocketNumber """")
      Case  "ClientDC": GuiPrint(ServerLogHwnd, "Client """ EventInfo.SocketNumber """ disconnected")
      Case  "DCClient": GuiPrint(ServerLogHwnd, "Disconnected client """ EventInfo.SocketNumber """")
      Case  "Shutdown": GuiPrint(ServerLogHwnd, "Shutdown")
      Case  "SendFail": GuiPrint(ServerLogHwnd, "Sending to client """ EventInfo.SocketNumber """ failed, details in EventInfo")
      Case     "Error": GuiPrint(ServerLogHwnd, "`r`nError: " EventInfo.Error
                                              . "`r`nError code: " EventInfo.ErrorCode
                                              . "`r`nError description:`r`n" EventInfo.ErrorDescription)
    }
  }
  else if (SocketName = "Client") {
    Switch (Event) {
      Case "ConnInit": GuiPrint(ClientLogHwnd, "Connecting to """ EventInfo.Address ":" EventInfo.Port """")
      Case "ConnBusy": GuiPrint(ClientLogHwnd, "There is a connecting attempt in progress")
      Case "ConnDone": GuiPrint(ClientLogHwnd, "Connected to """ EventInfo.Address ":" EventInfo.Port """ successfully")
      Case "ConnFail": GuiPrint(ClientLogHwnd, "Connecting to """ EventInfo.Address ":" EventInfo.Port """ failed")
      Case "Received": GuiPrint(ClientLogHwnd, "Received """ EventInfo.Message  """")
      Case "ServerDC": GuiPrint(ClientLogHwnd, "Server disconnected")
      Case "Shutdown": GuiPrint(ClientLogHwnd, "Shutdown")
      Case "SendFail": GuiPrint(ClientLogHwnd, "Sending failed, details in EventInfo")
      Case    "Error": GuiPrint(ClientLogHwnd, "`r`nError: " EventInfo.Error
                                              . "`r`nError code: " EventInfo.ErrorCode
                                              . "`r`nError description:`r`n" EventInfo.ErrorDescription)
    }
  }
}

GuiPrint(Hwnd, Text) {
  Static Counter := []
  (Counter.HasKey(Hwnd)?Counter[Hwnd]++:Counter[Hwnd]:=1)
  L:=DllCall("SendMessage", "Ptr", Hwnd, "UInt", 0x00E, "Int", 0, "Int", 0)
  DllCall("SendMessage", "Ptr", Hwnd, "UInt", 0x0B1, "Int", L, "Int", L)
  DllCall("SendMessage", "Ptr", Hwnd, "UInt", 0x0C2, "Int", 0, "Str", (L?"`r`n":"") Counter[Hwnd] ". " Text)
  DllCall("SendMessage", "Ptr", Hwnd, "UInt", 0x115, "Int", 7, "Int", 0)
}
;------------------------------------------------------------------------------------------------------------------------------------------
Class Winsock { ; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=125911
  __New(Name, Callback) {
    Static WSAStartup
    if !(WSAStartup) {
      WSAStartup := DllCall("LoadLibrary", "Str", "Ws2_32", "Ptr"), VarSetCapacity(WSAData, 394+A_PtrSize)
      if (EC:=DllCall("Ws2_32\WSAStartup", "UShort", 0x0202, "Ptr", &WSAData))
        Return,, this.SocketError("Error starting Winsock", EC)
      if (NumGet(WSAData, 2, "UShort") != 0x0202)
        Return,, this.SocketError("Winsock version 2.2 not available")
    }
    this.Name := Name, this.Callback := Callback, this.CS := [], this.Socket := -1
  }

  WM_SOCKET(wParam, lParam) {
    Critical, -1
    Static TextBacklog
    if (wParam != this.Socket)
      Return
    Switch (lParam) {
      Case  "8":
        VarSetCapacity(SocketAddress, 16), SN := DllCall("Ws2_32\accept", "UInt", this.Socket, "UInt", &SocketAddress, "Int*", 16)
        Sock := new Winsock(this.Name, this.Callback), Sock.Parent := this, Sock.Socket := SN, Sock.EventProcRegister()
        SockInfo := {SocketNumber:SN, SocketAddress:DllCall("Ws2_32\inet_ntoa", "UInt", NumGet(SocketAddress,4),"AStr")}
        this.CS[SN] := Sock, this.CS[SN].Info := SockInfo, this.Callback(this.Name, "Accepted", SockInfo)
      Case  "1":
        if (this.CTimer)
          Return,, this.ReadBackedup := True
        if (DllCall("Ws2_32\ioctlsocket", "UInt", this.Socket, "UInt", 0x4004667F, "UInt*", DataSize) = -1)
          Return,, TextBacklog := this.SocketError("WM_SOCKET > Read > ioctlsocket")
        VarSetCapacity(DataBuffer, DataSize)
        if (DllCall("Ws2_32\recv", "UInt", this.Socket, "Ptr", &DataBuffer, "Int", DataSize, "Int", 0) = -1)
          Return,, TextBacklog := this.SocketError("WM_SOCKET > Read > recv")
        if (SubStr(Text := StrGet(&DataBuffer, DataSize, "UTF-8"), 0) != Chr(3))
          Return,, TextBacklog .= Text
        else if (TextBacklog)
          Text := TextBacklog Text, TextBacklog := ""
        Loop, parse, % RTrim(Text, Chr(3)), % Chr(3)
          this.Callback(this.Name, "Received", {SocketNumber:this.Socket, Message:A_LoopField})
      Case "32":
        if (this.Parent) {
          this.CloseSocket(), this.Parent.CS.Delete(wParam), this.Callback(this.Name, "ClientDC", {SocketNumber:wParam})
        } else this.CloseSocket(), this.Callback(this.Name, "ServerDC", "")
    }
  }

  Listen(Address, Port) {
    if (this.CTimer)
      Return,, this.Callback(this.Name, "ConnBusy", "")
    (this.Socket=-1?_:this.Disconnect()), VarSetCapacity(Hints, 16+(4*A_PtrSize), 0), NumPut(1,Hints,8,"Int"), NumPut(6,Hints,12,"Int")
    if (EC:=DllCall("Ws2_32\getaddrinfo", "AStr", Address, "AStr", Port, "Ptr", &Hints, "Ptr*", ai))
      Return,, this.SocketError("Bind > getaddrinfo", EC)
    this.Socket := DllCall("Ws2_32\socket", "Int", 2, "Int", 1, "Int", 6, "UInt"), this.EventProcRegister()
    if (EC:=DllCall("Ws2_32\bind", "UInt", this.Socket, "Ptr", NumGet(ai+0,16+(2*A_PtrSize),"Ptr"), "UInt", NumGet(ai+0,16,"UPtr"),"Int"))
      Return,, DllCall("Ws2_32\freeaddrinfo", "Ptr", ai) this.SocketError("Listen > bind", EC)
    if (EC:=DllCall("Ws2_32\listen", "UInt", this.Socket, "Int", 32))
      Return,, DllCall("Ws2_32\freeaddrinfo", "Ptr", ai) this.SocketError("Listen > listen", EC)
    this.Serving := True, VarSetCapacity(sa, 16), DllCall("Ws2_32\getsockname", "UInt", this.Socket, "UInt", &sa, "Int*", 16)
    Address := DllCall("Ws2_32\inet_ntoa", "UInt", NumGet(sa,4),"AStr"), Port := DllCall("Ws2_32\htons", "UShort", NumGet(sa,2,"UShort"))
    DllCall("Ws2_32\freeaddrinfo", "Ptr", ai), this.Callback(this.Name, "Listening", {Address:Address, Port:Port})
  }

  Connect(Address, Port, Timeout := 3000) {
    Critical, -1
    if (this.CTimer)
      Return,, this.Callback(this.Name, "ConnBusy", "")
    (this.Socket=-1?_:this.Disconnect()), VarSetCapacity(Hints, 16+(4*A_PtrSize), 0), NumPut(1,Hints,8,"Int"), NumPut(6,Hints,12,"Int")
    if (EC:=DllCall("Ws2_32\getaddrinfo", "AStr", Address, "AStr", Port, "Ptr", &Hints, "Ptr*", ai))
      Return,, this.SocketError("Connect > getaddrinfo", EC)
    this.Socket := DllCall("Ws2_32\socket", "Int", 2, "Int", 1, "Int", 6), this.EventProcRegister()
    this.Callback(this.Name, "ConnInit", {Address:Address, Port:Port})
    this.CTimer := Timer := ObjBindMethod(this, "ConnectingTimeout", Address, Port, ai, A_TickCount, Timeout)
    SetTimer, % Timer, 1
  }

  ConnectingTimeout(Address, Port, ai, StartTime, Timeout) {
    if (this.CTimerCancel) {
      if (DllCall("Ws2_32\send", "UInt", this.Socket, "Ptr", 0, "Int", 0, "Int", 0) = 0)
        this.Callback(this.Name, "ConnDone", {Address:Address, Port:Port})
      DllCall("Ws2_32\freeaddrinfo", "Ptr", ai), this.CTimerCancel := False, Timer := this.CTimer, this.CTimer := "", this.CloseSocket()
      this.Callback(this.Name, "Shutdown", "")
      SetTimer, % Timer, Delete
      Return
    }
    DllCall("Ws2_32\connect", "UInt", this.Socket, "UPtr", NumGet(ai+0,16+(2*A_PtrSize),"Ptr"),"UInt", NumGet(ai+0,16,"UPtr"))
    if (DllCall("Ws2_32\WSAGetLastError") = 10056) {
      DllCall("Ws2_32\freeaddrinfo", "Ptr", ai), this.Callback(this.Name, "ConnDone", {Address:Address, Port:Port})
      Timer := this.CTimer, this.CTimer := "", (this.ReadBackedup?this.ReadBackedup := this.WM_SOCKET(this.Socket, 1, 0):_)
      SetTimer, % Timer, Delete
      Return
    }
    if ((A_TickCount - StartTime) > Timeout) {
      DllCall("Ws2_32\freeaddrinfo", "Ptr", ai), this.CloseSocket(), Timer := this.CTimer, this.CTimer := ""
      this.Callback(this.Name, "ConnFail", {Address:Address, Port:Port})
      SetTimer, % Timer, Delete
    }
  }

  Send(P1, P2 := "") {
    if (this.Socket = -1)
      Return
    if (this.CTimer)
      Return,, this.Callback(this.Name, "ConnBusy", "")
    VarSetCapacity(TextBuffer, StrPut(Text:=(P2?P2:P1), "UTF-8")), Length := (StrPut(Text Chr(3), &TextBuffer, "UTF-8")-1)
    if (this.Serving) {
      if (P2) {
        if (this.CS.HasKey(P1))
          if (DllCall("Ws2_32\send", "UInt", P1, "Ptr", &TextBuffer, "Int", Length, "Int", 0) = -1) {
            EC := DllCall("Ws2_32\WSAGetLastError"), VarSetCapacity(Desc, 2000, 32)
            DllCall("FormatMessage", "UInt", 0x1000, "UInt", 0, "UInt", EC, "UInt", 0x800, "UInt", &Desc, "UInt", 500, "UInt", 0)
            this.Callback(this.Name, "SendFail", {SocketNumber:P1, Message:Text, Code:EC, Description:Desc})
          }
      } else {
        For i, v in this.CS
          if (DllCall("Ws2_32\send", "UInt", v.Info.SocketNumber, "Ptr", &TextBuffer, "Int", Length, "Int", 0) = -1) {
            EC := DllCall("Ws2_32\WSAGetLastError"), VarSetCapacity(Desc, 2000, 32)
            DllCall("FormatMessage", "UInt", 0x1000, "UInt", 0, "UInt", EC, "UInt", 0x800, "UInt", &Desc, "UInt", 500, "UInt", 0)
            this.Callback(this.Name, "SendFail", {SocketNumber:v.Info.SocketNumber, Message:Text, Code:EC, Description:Desc})
          }
      }
    } else {
      if (DllCall("Ws2_32\send", "UInt", this.Socket, "Ptr", &TextBuffer, "Int", Length, "Int", 0) = -1) {
        EC := DllCall("Ws2_32\WSAGetLastError"), VarSetCapacity(Desc, 2000, 32)
        DllCall("FormatMessage", "UInt", 0x1000, "UInt", 0, "UInt", EC, "UInt", 0x800, "UInt", &Desc, "UInt", 500, "UInt", 0)
        this.Callback(this.Name, "SendFail", {Message:Text, Code:EC, Description:Desc})
      }
    }
  }

  Disconnect(SN := "") {
    if (this.CTimer)
      Return,, this.CTimerCancel := True
    if (this.Socket = -1)
      Return
    if !(SN) {
      if (this.Serving) {
        For i, v in this.CS
          v.CloseSocket()
        this.CloseSocket(), this.CS := [], this.Callback(this.Name, "Shutdown", "")
      }
      else
        this.CloseSocket(), this.Callback(this.Name, "Shutdown", "")
    }
    else if (this.Serving)
      if (this.CS.HasKey(SN))
        this.CS[SN].CloseSocket(), this.CS.Delete(SN), this.Callback(this.Name, "DCClient", {SocketNumber:SN})
  }

  CloseSocket() {
    this.EventProcRegister(False)
    if (DllCall("Ws2_32\closesocket", "UInt", this.Socket, "Int") = -1)
      this.SocketError("CloseSocket > closesocket")
    this.Serving := False, this.Socket := -1
  }

  EventProcRegister(R := True) {
    if (DllCall("Ws2_32\WSAAsyncSelect", "UInt", this.Socket, "Ptr", A_ScriptHwnd, "UInt", 0x9987, "UInt", (R?0x3FF:0)) = -1)
      Return,, this.SocketError("EventProc > WSAAsyncSelect")
    (this.Bound?OnMessage(0x9987, this.Bound, this.Bound := False):OnMessage(0x9987, this.Bound := ObjBindMethod(this, "WM_SOCKET")))
  }

  SocketError(Error, ErrorCode := "") {
    ErrorCode := (ErrorCode?ErrorCode:DllCall("Ws2_32\WSAGetLastError")), VarSetCapacity(Description, 2000, 32)
    DllCall("FormatMessage", "UInt", 0x1000, "UInt", 0, "UInt", ErrorCode, "UInt", 0x800, "UInt", &Description, "UInt", 500, "UInt", 0)
    this.Callback(this.Name, "Error", {Error:Error, ErrorCode:ErrorCode, ErrorDescription:(ErrorCode?Description:"-")})
  }
}

Sorry for how sporadic this post is, i didn't know how to structure it nicely :/

When creating a new instance - ClassInstance := new Winsock(P1, P2)
P1 is the socket name, i recommend having ClassInstance variable the same as the socket name to avoid confusion.
P2 is the callback function, look at the template (SocketHandler) for all possible events, hopefully they are self-explanatory.

Socket.ahk and just winsock in general has issues when sending too fast, this class has a different approach to sending and receiving -
Each message ends with the End of Text character, this makes it possible to use Send() rapidly and messages are separated properly.
Delimiting also allows to properly receive multiple packets (when sending a large message, over 64KB, it gets split up into multiple packets)
Because of that, this class shouldn't be used with different winsock implementations.

When listening, Send() sends to all connected sockets, however when a connection is being accepted -
Case "Accepted": GuiPrint(ServerLogHwnd, "Accepted client """ EventInfo.SocketNumber " | " EventInfo.SocketAddress """")
EventInfo.SocketNumber can be saved for sending only to this specific socket connection - ClassInstance.Send(EventInfo.SocketNumber, Text)

Compared to socket.ahk, connecting is a lot different:
ClassInstance.Connect(Address, Port, Timeout)
It's non-blocking, meaning that the script doesn't hang while trying to connect.
If you set the timeout parameter to for example 30000 (30 seconds), it will continuously try to connect for that 30 seconds.
The connecting attempt can be cancelled by calling Disconnect()

When sending, if SendFail event occurs then you can check EventInfo.SocketNumber/Message/Code/Description to figure out what caused it,
otherwise it should be assumed that sending succeeded. I could have added an event that indicates successful send but it wouldn't be very reliable,
you can implement some sort of confirmation where the peer responds that a message has been received for extra precaution.

Before deleting a class instance, you should always call Disconnect() first.
Otherwise the class might not delete at all because there's a circular reference.


That's pretty much all the major features/differences, here are some random final notes:
• I didn't write this class with readability in mind, if someone suggests an interesting or useful feature i'm down to implement it!
• Sadly, getaddrinfo can cause the script to hang, you can test it with trying to connect to weird IP's like "123"
i don't think there are any work-arounds for it but if someone knows some black magic, please tell me!
• I didn't do much testing with receiving messages from multiple sockets at the same time,
i think there could be a "bug" where messages get mixed up, if someone complains about it i'll fix it.
• Rapid sending was tested with the code below, you can play around with it if you want..
F1::SetTimer, TestingTimer, % ((Toggle:=!Toggle)?1:"Delete")
TestingTimer:
Count++
Server.Send(Count)
Client.Send(Count)
Return
• I probably won't dabble in different socket types like UDP, however i:
- Might add IPv6 support (probably not, it's a big headache)
- Might add binary and file transfer (probably not, i personally don't need these features)

That's pretty much it!
Hopefully someone finds this useful c.c
Last edited by MiM on 12 Feb 2024, 20:20, edited 3 times in total.
User avatar
elModo7
Posts: 217
Joined: 01 Sep 2017, 02:38
Location: Spain
Contact:

Re: Yet another winsock class (TCP/IPv4, Text only)

11 Feb 2024, 12:37

Works great! Just a quick note, it's AHKU64 compatible only I'm on an old PC right now and AHKU32 is not compatible with it.

Might do some more testing since I used to have problems when dealing with big ingests (in my case it was not when sending but when receiving packets way too quickly from other languages, ie Godot).
If I get some time I may post the results here.

Thank you for sharing :thumbup:
User avatar
MiM
Posts: 61
Joined: 20 Apr 2021, 04:31

Re: Yet another winsock class (TCP/IPv4, Text only)

11 Feb 2024, 13:04

elModo7 wrote: Works great! Just a quick note, it's AHKU64 compatible only I'm on an old PC right now and AHKU32 is not compatible with it.
Damnit, i deliberately only made it x64... i'll make it x32 compatible when i get bored. Should be x32 compatible now.
elModo7 wrote: Might do some more testing since I used to have problems when dealing with big ingests (in my case it was not when sending but when receiving packets way too quickly from other languages, ie Godot).
Please read the Because of that, this class shouldn't be used with different winsock implementations. paragraph!
(i don't want you to waste your time)

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: ordinarier and 62 guests