客户端:
;Client #Include Socket.ahk myTcp := new SocketTCP() myTcp.connect("localhost", 12345) MsgBox, % myTcp.recvText() myTcp.sendText("Hello Server!") ExitApp
服务端:
;Server #Include Socket.ahk myTcp := new SocketTCP() myTcp.bind("addr_any", 12345) myTcp.listen() myTcp.onAccept := Func("OnTCPAccept") return OnTCPAccept(){ global myTcp newTcp := myTcp.accept() newTcp.sendText("Hello Client!") MsgBox, % newTcp.recvText() ExitApp }
用到的库文件,将这个库文件保存为socket.ahk:
;~ https://autohotkey.com/board/topic/94376-socket-class-%c3%bcberarbeitet/ class Socket { static __eventMsg := 0x9987 __New(s=-1) { static init if (!init) { DllCall("LoadLibrary", "str", "ws2_32", "ptr") VarSetCapacity(wsadata, 394+A_PtrSize) DllCall("ws2_32\WSAStartup", "ushort", 0x0000, "ptr", &wsadata) DllCall("ws2_32\WSAStartup", "ushort", NumGet(wsadata, 2, "ushort"), "ptr", &wsadata) OnMessage(Socket.__eventMsg, "SocketEventProc") init := 1 } this.socket := s } __Delete() { this.disconnect() } __Get(k, v) { if (k="size") return this.msgSize() } connect(host, port) { if ((this.socket!=-1) || (!(faddr := next := this.__getAddrInfo(host, port)))) return 0 while (next) { sockaddrlen := NumGet(next+0, 16, "uint") sockaddr := NumGet(next+0, 16+(2*A_PtrSize), "ptr") if ((this.socket := DllCall("ws2_32\socket", "int", NumGet(next+0, 4, "int"), "int", this.__socketType, "int", this.__protocolId, "ptr"))!=-1) { if ((r := DllCall("ws2_32\WSAConnect", "ptr", this.socket, "ptr", sockaddr, "uint", sockaddrlen, "ptr", 0, "ptr", 0, "ptr", 0, "ptr", 0, "int"))=0) { DllCall("ws2_32\freeaddrinfo", "ptr", faddr) return Socket.__eventProcRegister(this, 0x21) } this.disconnect() } next := NumGet(next+0, 16+(3*A_PtrSize), "ptr") } this.lastError := DllCall("ws2_32\WSAGetLastError") return 0 } bind(host, port) { if ((this.socket!=-1) || (!(faddr := next := this.__getAddrInfo(host, port)))) return 0 while (next) { sockaddrlen := NumGet(next+0, 16, "uint") sockaddr := NumGet(next+0, 16+(2*A_PtrSize), "ptr") if ((this.socket := DllCall("ws2_32\socket", "int", NumGet(next+0, 4, "int"), "int", this.__socketType, "int", this.__protocolId, "ptr"))!=-1) { if (DllCall("ws2_32\bind", "ptr", this.socket, "ptr", sockaddr, "uint", sockaddrlen, "int")=0) { DllCall("ws2_32\freeaddrinfo", "ptr", faddr) return Socket.__eventProcRegister(this, 0x29) } this.disconnect() } next := NumGet(next+0, 16+(3*A_PtrSize), "ptr") } this.lastError := DllCall("ws2_32\WSAGetLastError") return 0 } listen(backlog=32) { return (DllCall("ws2_32\listen", "ptr", this.socket, "int", backlog)=0) ? 1 : 0 } accept() { if ((s := DllCall("ws2_32\accept", "ptr", this.socket, "ptr", 0, "int", 0, "ptr"))!=-1) { newsock := new Socket(s) newsock.__protocolId := this.__protocolId newsock.__socketType := this.__socketType Socket.__eventProcRegister(newsock, 0x21) return newsock } return 0 } disconnect() { Socket.__eventProcUnregister(this) DllCall("ws2_32\closesocket", "ptr", this.socket, "int") this.socket := -1 return 1 } msgSize() { VarSetCapacity(argp, 4, 0) if (DllCall("ws2_32\ioctlsocket", "ptr", this.socket, "uint", 0x4004667F, "ptr", &argp)!=0) return 0 return NumGet(argp, 0, "int") } send(addr, length) { if ((r := DllCall("ws2_32\send", "ptr", this.socket, "ptr", addr, "int", length, "int", 0, "int"))<=0) return 0 return r } sendText(msg, encoding="UTF-8") { VarSetCapacity(buffer, length := (StrPut(msg, encoding)*(((encoding="utf-16")||(encoding="cp1200")) ? 2 : 1))) StrPut(msg, &buffer, encoding) return this.send(&buffer, length) } recv(byref buffer, wait=1) { while ((wait) && ((length := this.msgSize())=0)) sleep, 100 if (length) { VarSetCapacity(buffer, length) if ((r := DllCall("ws2_32\recv", "ptr", this.socket, "ptr", &buffer, "int", length, "int", 0))<=0) return 0 return r } return 0 } recvText(wait=1, encoding="UTF-8") { if (length := this.recv(buffer, wait)) return StrGet(&buffer, length, encoding) return } __getAddrInfo(host, port) { a := ["127.0.0.1", "0.0.0.0", "255.255.255.255", "::1", "::", "FF00::"] conv := {localhost:a[1], addr_loopback:a[1], inaddr_loopback:a[1], addr_any:a[2], inaddr_any:a[2], addr_broadcast:a[3] , inaddr_broadcast:a[3], addr_none:a[3], inaddr_none:a[3], localhost6:a[4], addr_loopback6:a[4], inaddr_loopback6:a[4] , addr_any6:a[5], inaddr_any:a[5], addr_broadcast6:a[6], inaddr_broadcast6:a[6], addr_none6:a[6], inaddr_none6:a[6]} if (conv[host]) host := conv[host] VarSetCapacity(hints, 16+(4*A_PtrSize), 0) NumPut(this.__socketType, hints, 8, "int") NumPut(this.__protocolId, hints, 12, "int") if ((r := DllCall("ws2_32\getaddrinfo", "astr", host, "astr", port, "ptr", &hints, "ptr*", next))!=0) { this.lastError := DllCall("ws2_32\WSAGetLastError") return 0 } return next } __eventProcRegister(obj, msg) { a := SocketEventProc(0, 0, "register", 0) a[obj.socket] := obj return (DllCall("ws2_32\WSAAsyncSelect", "ptr", obj.socket, "ptr", A_ScriptHwnd, "uint", Socket.__eventMsg, "uint", msg)=0) ? 1 : 0 } __eventProcUnregister(obj) { a := SocketEventProc(0, 0, "register", 0) a.remove(obj.socket) return (DllCall("ws2_32\WSAAsyncSelect", "ptr", obj.socket, "ptr", A_ScriptHwnd, "uint", 0, "uint", 0)=0) ? 1 : 0 } } SocketEventProc(wParam, lParam, msg, hwnd) { global Socket static a := [] Critical if (msg="register") return a if (msg=Socket.__eventMsg) { if (!isobject(a[wParam])) return 0 if ((lParam & 0xFFFF) = 1) return a[wParam].onRecv(a[wParam]) else if ((lParam & 0xFFFF) = 8) return a[wParam].onAccept(a[wParam]) else if ((lParam & 0xFFFF) = 32) { a[wParam].socket := -1 return a[wParam].onDisconnect(a[wParam]) } return 0 } return 0 } class SocketTCP extends Socket { static __protocolId := 6 ;IPPROTO_TCP static __socketType := 1 ;SOCK_STREAM } class SocketUDP extends Socket { static __protocolId := 17 ;IPPROTO_UDP static __socketType := 2 ;SOCK_DGRAM enableBroadcast() { VarSetCapacity(optval, 4, 0) NumPut(1, optval, 0, "uint") if (DllCall("ws2_32\setsockopt", "ptr", this.socket, "int", 0xFFFF, "int", 0x0020, "ptr", &optval, "int", 4)=0) return 1 return 0 } disableBroadcast() { VarSetCapacity(optval, 4, 0) if (DllCall("ws2_32\setsockopt", "ptr", this.socket, "int", 0xFFFF, "int", 0x0020, "ptr", &optval, "int", 4)=0) return 1 return 0 } }
感谢分享。请教大神,想把服务端改成手机扫描枪的电脑端。改MsgBox, % newTcp.recvText()为SendInput % newTcp.recvText()”{Enter}” ,删除ExitAPP。手机扫描枪app连接192.168.1.* 12345成功,扫第一个条码能正常接收并输出到光标处,后续再扫描的就不能输出了,手机app断开再连接,依然只输出第一个条码。请大神指点迷津,非常感谢!
这个太好用了
这个就是ahk浏览器吗?
跑起来了,但是大佬能不能描述一下实现的过程啊
内容中有个用到的库的代码,保存为Socket.ahk
有疑问请留言
1.大佬,能简述一下过程不。
2.跑不起来
Socket.ahk 在哪?