找回密码
 加入
搜索
楼主: wllx

如何 用TCP实现远程关机、重启

[复制链接]
发表于 2023-10-7 21:09:45 | 显示全部楼层
以前写的 TCP服务端,你可以参考一下。
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=                                                                                                 ;程序图标
#AutoIt3Wrapper_UseX64=n                                                                                         ;是否编译为64位程序(y/n)
#AutoIt3Wrapper_OutFile=                                                                                         ;输出的Exe名称
#AutoIt3Wrapper_OutFile_x64=                                                                                 ;64位输出的Exe名称
#AutoIt3Wrapper_UseUpx=n                                                                                         ;是否使用UPX压缩(y/n) 注:开启压缩极易引起误报问题
#AutoIt3Wrapper_Res_Comment=http://www.autoitscript.com/autoit3/         ;程序注释
#AutoIt3Wrapper_Res_Description=AutoIt Team                                        ;文件说明
#AutoIt3Wrapper_Res_Fileversion=1.0.0.40
#AutoIt3Wrapper_Res_Field=Productname|AutoIt v3                                     ;产品名称
#AutoIt3Wrapper_Res_ProductVersion=1.0                                                                 ;产品版本
#AutoIt3Wrapper_Res_LegalCopyright=©1999-2021 AutoIt Team                          ;版权
#AutoIt3Wrapper_Res_Language=2052                                                                         ;语言, 英语=2057/中文=2052
#AutoIt3Wrapper_Res_Field=OriginalFilename|AutoIt.exe                    ;原始文件名
#AutoIt3Wrapper_Res_Field=InternalName|AutoIt_exe                               ;内部名称
#AutoIt3Wrapper_Res_FileVersion_AutoIncrement=y                                                 ;自动更新版本 y/n/p=自动/不自动/询问
#AutoIt3Wrapper_Res_RequestedExecutionLevel=asInvoker                                 ;请求权限: None/asInvoker/highestAvailable/requireAdministrator
#AutoIt3Wrapper_Run_Tidy=n                                                                                         ;编译前自动整理脚本(y/n)
#AutoIt3Wrapper_Res_HiDpi=p                                                                                         ;支持DPi感知
#Au3Stripper_Parameters=/sf=1 /sv=1
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#cs ____________________________________

        欢迎使用 AutoIt v3 中文版 !
        Au3版本:        3.3.14.5
        脚本作者:
        脚本功能:
        更新日志:
        联系方式:

#ce _______________脚本开始_________________
#include <Array.au3>
#include <WinAPISys.au3>
#include <WinAPIProc.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiListView.au3>
#include <GuiEdit.au3>
Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)
Opt("GUICloseOnESC", 0)
Global Const $FD_READ = 1
Global Const $FD_WRITE = 2
Global Const $FD_ACCEPT = 8
Global Const $FD_CONNECT = 16
Global Const $FD_CLOSE = 32
Global Const $FD_SETSIZE = 32 ;定义监听客户端数量
Global Const $tagFd_set = "UINT fd_count;UINT fd_array[" & $FD_SETSIZE & "]"
Global $hDLL_WS2_32 = DllOpen("ws2_32.dll")
Global Const $FD_MAX_EVENTS = 10
Global $NetEvent = DllStructCreate("long lNetworkEvents;int iErrorCode[" & $FD_MAX_EVENTS & "];")
Global $UDP_Event = DllStructCreate("handle Event;")
Global $UDP_Socket
Global $UDP_port = 6800 ;定义监听端口
Global $TCP_MAX = 2
Global $TCP_port[$TCP_MAX] = [20001, 20002] ;定义监听端口
Global $TCP_Socket[$TCP_MAX]
Global $TCP_Event = DllStructCreate("handle Event[" & $TCP_MAX & "];")
Global $Client_Socket = DllStructCreate($tagFd_set)
Global $test, $hGUI, $idEdit, $idListview
Global $SendGUI, $Button1, $Input, $Num, $data
Global $fd_Array[$FD_SETSIZE][10]
Opt("GUIResizeMode", 1)
Global $HiDpi
If @Compiled Then
        If _IsProcessDPIAware() Then
                $HiDpi = _GetDpi()
        Else
                $HiDpi = 1
        EndIf
Else
        _SetProcessDPIAware()
        $HiDpi = _GetDpi()
EndIf

TCPStartup()
$UDP_Socket = UDPOpen("255.255.255.255", $UDP_port, 1)
UDPSend($UDP_Socket, Binary("0x01000000A00F00000000000000000000")) ;发送广播消息,查询是否存在服务。
$data = UDPRecv($UDP_Socket, 4096, 1) ;接收消息,耗时 50毫秒。
UDPCloseSocket($UDP_Socket)

If $data <> "" Then
        Exit MsgBox(262144 + 65536 + 64, "警告", "发现内网服务端:" & BinaryToString($data) & " 退出程序.")
EndIf

CreateGUI()
#Region 创建监听端口
For $i = 0 To $TCP_MAX - 1
        $TCP_Socket[$i] = TCPListen("0.0.0.0", $TCP_port[$i], 1024)
        If @error Then Exit MsgBox(262144 + 65536 + 64, "TCP端口冲突", "TCP端口被占用:" & $TCP_port[$i])
        _Echo($idEdit, "监听TCP端口:" & $TCP_port[$i])
        $TCP_Event.Event($i + 1) = _WinAPI_CreateEvent(0, True, False) ;创建事件对象, 为无信号,手动重置
        _SockEventSelect($TCP_Socket[$i], $TCP_Event.Event($i + 1), $FD_ACCEPT) ;设置到事件模式
Next

$UDP_Socket = UDPBind("0.0.0.0", $UDP_port)
If @error Then Exit MsgBox(262144 + 65536 + 64, "UDP端口冲突", "UDP端口被占用:" & $UDP_port)
_Echo($idEdit, "监听UDP端口:" & $UDP_port)
$UDP_Event.Event(1) = _WinAPI_CreateEvent(0, True, False) ;创建事件对象, 为无信号,手动重置
_SockEventSelect($UDP_Socket[1], $UDP_Event.Event(1), $FD_READ) ;设置到事件模式
#EndRegion 创建监听端口
_Echo($idEdit, "启动完成。")
OnAutoItExitRegister("_Exit")
AdlibRegister("_Timeout", 1000 * 60) ;活动连接心跳检测

While 1
        _TCP_Event($Client_Socket)
        _UDP_Event()
        _Client_Event($Client_Socket)
        Sleep(5)
WEnd

Func _Data_Out($iSocket, $iDate)
        If BinaryLen($iDate) < 20 Then
                _TCPSend($iSocket, "x")
                ;_Echo($idEdit, "收到心跳包:" & $iDate)
        Else
                _Echo($idEdit, "收到数据:" & $iDate)
        EndIf
EndFunc   ;==>_Data_Out

Func _UDP_Event() ;处理UDP网路事件
        Local $iObjects, $data, $aRet
        Local $DateLen = 4096
        $iObjects = _WinAPI_WaitForMultipleObjects(1, $UDP_Event, False, 0) ;检测信号状态,等待5毫秒
        Switch $iObjects
                Case 0
                        _WinAPI_ResetEvent($UDP_Event.Event($iObjects + 1)) ;设置指定事件对象为无信号状态
                        $aRet = DllCall("Ws2_32.dll", "int", "ioctlsocket", "uint", $UDP_Socket[1], "long", 0x4004667F, "ulong*", 0) ;查询接收缓冲区数据长度
                        If $aRet[0] = 0 Then $DateLen = $aRet[3]
                        $data = UDPRecv($UDP_Socket, $DateLen, 3)
                        If Not @error Then
                                If String($data[0]) == "0x01000000A00F00000000000000000000" Then
                                        $UDP_Socket[2] = $data[1]
                                        $UDP_Socket[3] = $data[2]
                                        UDPSend($UDP_Socket, @IPAddress1 & ";" & $TCP_port[0] & ";" & $TCP_port[1])
                                EndIf
                        EndIf
                Case -1 ;检测信号状态失败
        EndSwitch
EndFunc   ;==>_UDP_Event

Func _TCP_Event(ByRef $tFd_set) ;处理TCP接入请求事件
        Local $iObjects, $iSocket, $NewIP, $iListItem, $Index
        $iObjects = _WinAPI_WaitForMultipleObjects($TCP_MAX, $TCP_Event, False, 0) ;检测信号状态,等待5毫秒
        Switch $iObjects
                Case 0 To $TCP_MAX - 1
                        ;_WinAPI_ResetEvent($TCP_Event.Event($iObjects + 1)) ;设置指定事件对象为无信号状态
                        ;//添加的代码
                        If _WSAEnumNetworkEvents($TCP_Socket[$iObjects], $TCP_Event.Event($iObjects + 1)) Then ;择网络事件
                                If BitAND($NetEvent.lNetworkEvents(1), $FD_ACCEPT) Then
                                        If $NetEvent.iErrorCode(3) = 0 Then
                                                $iSocket = TCPAccept($TCP_Socket[$iObjects])
                                                If $iSocket <> -1 Then
                                                        $NewIP = _SocketToIP($iSocket)
                                                        If $tFd_set.fd_count(1) >= $FD_SETSIZE Then
                                                                _Echo($idEdit, "!超出最大连接数:" & $FD_SETSIZE & " 断开新连接")
                                                                TCPCloseSocket($iSocket)
                                                        Else
                                                                _FD_SET($iSocket, $tFd_set)
                                                                $Index = _Array_SET($iSocket, $fd_Array)
                                                                $fd_Array[$Index][2] = GUICtrlCreateListViewItem($NewIP[0], $idListview)
                                                                $fd_Array[$Index][3] = $NewIP[0]
                                                                $fd_Array[$Index][4] = TimerInit()
                                                                _Echo($idEdit, "新连接,来自IP:" & $NewIP[0] & " 源端口:" & $NewIP[1] & " 目的端口:" & $NewIP[3] & " 连接数:" & $tFd_set.fd_count(1))
                                                        EndIf
                                                EndIf
                                        Else
                                                ConsoleWrite("WSAEnumNetworkEvents failed with error code:" & $NetEvent.iErrorCode(3))
                                        EndIf
                                EndIf
                        EndIf
                        ;//添加的代码
                Case -1 ;检测信号状态失败
        EndSwitch
EndFunc   ;==>_TCP_Event

Func _Timeout()
        Local $i
        For $i = $FD_SETSIZE - 1 To 0 Step -1
                If $fd_Array[$i][4] == "" Then ContinueLoop
                If TimerDiff($fd_Array[$i][4]) > 1000 * 10 Then ;活动连接无心跳10秒,关闭连接
                        GUICtrlDelete($fd_Array[$i][2])
                        TCPCloseSocket($fd_Array[$i][1])
                        _Echo($idEdit, "连接超时,来自IP:" & $fd_Array[$i][3])
                        _FD_CLR($fd_Array[$i][1], $Client_Socket)
                        _Array_CLR($fd_Array[$i][1], $fd_Array)
                EndIf
        Next
EndFunc   ;==>_Timeout

Func _TCPRecv($iSocket, $iDataLen)
        Local $DateLen
        Local $Index = _Array_ISSET($iSocket, $fd_Array)
        If $Index = -1 Then Return
        $fd_Array[$Index][4] = TimerInit() ;写入时间戳
        Local $iData = TCPRecv($iSocket, $iDataLen, 1)
        If @error Then Return SetError(@error, @extended, "") ;错误处理 待完善
        If IsBinary($fd_Array[$Index][5]) Then ;检查缓存
                $fd_Array[$Index][5] = Binary($fd_Array[$Index][5] + $iData)
        Else
                $fd_Array[$Index][5] = $iData
        EndIf
        While 1
                If BinaryLen($fd_Array[$Index][5]) < 4 Then ExitLoop
                $DateLen = Int(BinaryMid($fd_Array[$Index][5], 1, 4))
                If BinaryLen($fd_Array[$Index][5]) < $DateLen + 4 Then
                        ExitLoop
                ElseIf BinaryLen($fd_Array[$Index][5]) = $DateLen + 4 Then
                        _Data_Out($iSocket, BinaryMid($fd_Array[$Index][5], 5))
                        $fd_Array[$Index][5] = ""
                        ExitLoop
                EndIf
                _Data_Out($iSocket, BinaryMid($fd_Array[$Index][5], 5, $DateLen))
                $fd_Array[$Index][5] = BinaryMid($fd_Array[$Index][5], $DateLen + 5)
        WEnd
EndFunc   ;==>_TCPRecv

Func _TCPSend($iSocket, $dData)
        If $dData == "" Then Return
        If Not IsBinary($dData) Then $dData = StringToBinary($dData)
        Local $dataLen = BinaryLen($dData)
        Local $byte = Binary(Binary(Ptr($dataLen)) + $dData)
        Local $iRet = TCPSend($iSocket, $byte)
        If @error Then Return SetError(@error, 0, 0)
        Return $iRet
EndFunc   ;==>_TCPSend

Func _Echo($hID, $sText = "")
        If Not StringIsASCII($sText) Then $sText = String($sText)
        Local $LogTime = @YEAR & "-" & @MON & "-" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & $sText & @CRLF
        Local $hWnd = GUICtrlGetHandle($hID)
        Local $Len = StringLen($LogTime)
        Local $Text = $LogTime & GUICtrlRead($hID)
        If _GUICtrlEdit_GetLineCount($hWnd) > 300 Then
                $Len += _GUICtrlEdit_LineIndex($hWnd, 299)
                $Text = StringLeft($Text, $Len)
        EndIf
        GUICtrlSetData($hID, $Text)
EndFunc   ;==>_Echo

Func CreateGUI()
        Local $Width = 880, $Height = 680, $idContextmenu
        $hGUI = GUICreate("广播转发 - 支持" & $FD_SETSIZE & "接入", $Width, $Height + 48, -1, -1) ;创建窗口
        GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
        GUICtrlCreateGroup("客户端列表", 5, 10, $Width - 10, 500)
        $idListview = GUICtrlCreateListView("编号|", 10, 25, $Width - 20, 480, $LVS_SHOWSELALWAYS, $LVS_EX_FULLROWSELECT + $LVS_EX_GRIDLINES + $LVS_EX_DOUBLEBUFFER) ;,$LVS_SORTDESCENDING)
        _GUICtrlListView_SetColumnWidth($idListview, 0, $LVSCW_AUTOSIZE_USEHEADER)
        GUICtrlCreateGroup("消息日志", 5, 520, $Width - 10, 166)
        $idEdit = GUICtrlCreateEdit("", 15, 540, $Width - 30, 136, 0x50210804, $WS_EX_STATICEDGE)
        $idContextmenu = GUICtrlCreateContextMenu($idListview)
        ;创建菜单“所有客户机”主控件-全部
        GUICtrlCreateMenuItem("关闭连接", $idContextmenu)
        GUICtrlSetOnEvent(-1, "_Selected")
        GUICtrlCreateMenuItem("发送消息", $idContextmenu)
        GUICtrlSetOnEvent(-1, "_Selected_Send")
        GUISetState(@SW_SHOW)
EndFunc   ;==>CreateGUI

Func _Client_Event(ByRef $tFd_set) ;处理客户端的网路事件
        Local $iSocket, $iData, $NewIP, $aRet, $Index, $DateLen
        Local $count = $tFd_set.fd_count(1)
        If $count < 1 Then Return
        Local $Fd_Socket = DllStructCreate($tagFd_set)
        Local $tFd_set_dat = DllStructCreate("byte[" & $count * 4 + 4 & "];", DllStructGetPtr($tFd_set))
        Local $Fd_Socket_dat = DllStructCreate("byte[" & $count * 4 + 4 & "];", DllStructGetPtr($Fd_Socket))
        DllStructSetData($Fd_Socket_dat, 1, DllStructGetData($tFd_set_dat, 1)) ;创建结构体副本
        If _Select($Fd_Socket) Then ;查询是否有网络事件
                For $i = 0 To $Fd_Socket.fd_count(1) - 1
                        $iSocket = $Fd_Socket.fd_array($i + 1)
                        If _FD_ISSET($iSocket, $Fd_Socket) Then ;检查套接字是否存在
                                $NewIP = _SocketToIP($iSocket) ;查询套接字的源地址-目标地址
                                Local $DateLen = 4096
                                $aRet = DllCall("Ws2_32.dll", "int", "ioctlsocket", "uint", $iSocket, "long", 0x4004667F, "ulong*", 0) ;查询套接字接收缓冲区中的数据长度
                                If $aRet[0] = 0 Then
                                        If $aRet[3] > 0 Then
                                                _TCPRecv($iSocket, $aRet[3])
                                        Else
                                                TCPCloseSocket($iSocket)
                                                _FD_CLR($iSocket, $tFd_set)
                                                $Index = _Array_ISSET($iSocket, $fd_Array) ;查询套接字在数组中的位置
                                                If Not @error Then
                                                        GUICtrlDelete($fd_Array[$Index][2])
                                                        _Array_CLR($iSocket, $fd_Array) ;清理数组
                                                EndIf
                                                _Echo($idEdit, "断开连接,来自IP:" & $NewIP[0] & " 源端口:" & $NewIP[1] & " 目的端口:" & $NewIP[3])
                                        EndIf
                                Else
                                        _TCPRecv($iSocket, 4096)
                                EndIf
                        EndIf
                Next
        EndIf
EndFunc   ;==>_Client_Event

Func _Select(ByRef $tFd_set)
        Local $timeval = DllStructCreate("int tv_sec;int tv_usec")
        Local $result = DllCall("Ws2_32.dll", "int", "select", "int", Null, "struct*", $tFd_set, "ptr", 0, "ptr", 0, "struct*", $timeval)
        If $result[0] <= 0 Then Return False
        Return True
EndFunc   ;==>_Select

Func _Array_SET($iSocket, ByRef $tArray_set)
        If Not IsArray($tArray_set) Then Return SetError(2, False, False)
        If $tArray_set[0][0] = "" Then $tArray_set[0][0] = 0
        Local $ROWS = UBound($tArray_set)
        Local $iCount = $tArray_set[0][0]
        For $i = 0 To $iCount - 1
                If $tArray_set[$i][1] = $iSocket Then
                        ExitLoop
                EndIf
        Next
        If $i = $iCount Then
                If $iCount < $ROWS Then
                        $tArray_set[$i][1] = $iSocket
                        $tArray_set[0][0] = $iCount + 1
                EndIf
        EndIf
        Return $tArray_set[0][0] - 1
EndFunc   ;==>_Array_SET

Func _Array_CLR($iSocket, ByRef $tArray_set)
        Local $COLUMNS = UBound($tArray_set, 2)
        Local $iCount = $tArray_set[0][0]
        For $i = 0 To $iCount - 1
                If $tArray_set[$i][1] = $iSocket Then
                        While ($i < $iCount - 1)
                                For $s = 1 To $COLUMNS - 1
                                        $tArray_set[$i][$s] = $tArray_set[$i + 1][$s]
                                Next
                                $i += 1
                        WEnd
                        For $s = 1 To $COLUMNS - 1
                                $tArray_set[$i][$s] = Null
                        Next
                        $tArray_set[0][0] = $iCount - 1
                        ExitLoop
                EndIf
        Next
EndFunc   ;==>_Array_CLR

Func _Array_ISSET($iSocket, ByRef $tArray_set)
        If Not IsArray($tArray_set) Then Return SetError(2, False, -1)
        If $tArray_set[0][0] = "" Then $tArray_set[0][0] = 0
        Local $Ret
        Local $COLUMNS = UBound($tArray_set, 2)
        Local $iCount = $tArray_set[0][0]
        For $i = 0 To $iCount - 1
                If $tArray_set[$i][1] = $iSocket Then
                        $Ret = $i
                        ExitLoop
                EndIf
        Next
        If $Ret == "" Then Return SetError(2, False, -1)
        Return $Ret
EndFunc   ;==>_Array_ISSET

Func _FD_SET($iSocket, ByRef $tFd_set)
        Local $iCount = DllStructGetData($tFd_set, "fd_count")
        For $i = 0 To $iCount - 1
                If DllStructGetData($tFd_set, "fd_Array", $i + 1) = $iSocket Then
                        ExitLoop
                EndIf
        Next
        If $i = $iCount Then
                If $iCount < $FD_SETSIZE Then
                        DllStructSetData($tFd_set, "fd_array", $iSocket, $i + 1)
                        DllStructSetData($tFd_set, "fd_count", $iCount + 1)
                EndIf
        EndIf
EndFunc   ;==>_FD_SET

Func _FD_CLR($iSocket, ByRef $tFd_set)
        Local $iCount = DllStructGetData($tFd_set, "fd_count")
        For $i = 0 To $iCount - 1
                If DllStructGetData($tFd_set, "fd_array", $i + 1) = $iSocket Then
                        While ($i < $iCount - 1)
                                DllStructSetData($tFd_set, "fd_array", DllStructGetData($tFd_set, "fd_array", $i + 2), $i + 1)
                                $i += 1
                        WEnd
                        DllStructSetData($tFd_set, "fd_array", 0, $i + 1)
                        DllStructSetData($tFd_set, "fd_count", $iCount - 1)
                        ExitLoop
                EndIf
        Next
EndFunc   ;==>_FD_CLR

Func _FD_ISSET($iSocket, ByRef $tFd_set)
        Local $aRet = DllCall($hDLL_WS2_32, "int", "__WSAFDIsSet", "UINT", $iSocket, "struct*", $tFd_set)
        Return $aRet[0]
EndFunc   ;==>_FD_ISSET

Func _WSAEnumNetworkEvents($hSocket, $hWnd)
        Local $iRet = DllCall($hDLL_WS2_32, "int", "WSAEnumNetworkEvents", "uint", $hSocket, "hwnd", $hWnd, "struct*", $NetEvent)
        If @error Then Return SetError(1, @error, False)
        If $iRet[0] <> 0 Then
                $iRet = DllCall($hDLL_WS2_32, "dword", "WSAGetLastError")
                Return SetError(2, $iRet[0], False)
        EndIf
        Return True
EndFunc   ;==>_WSAEnumNetworkEvents

Func _SockEventSelect($hSocket, $hWnd, $iEvent = 0)
        Local $iRet = DllCall($hDLL_WS2_32, "int", "WSAEventSelect", "uint", $hSocket, "hwnd", $hWnd, "int", $iEvent)
        If @error Then Return SetError(1, @error, False)
        If $iRet[0] <> 0 Then
                Return SetError(2, _WSAGetLastError(), False)
        EndIf
        Return True
EndFunc   ;==>_SockEventSelect

Func _WSAGetLastError()
        Local $iRet = DllCall($hDLL_WS2_32, "int", "WSAGetLastError")
        If @error Then
                SetExtended(1)
                Return 0
        EndIf
        Return $iRet[0]
EndFunc   ;==>_WSAGetLastError

Func _SocketToIP($hSocket)
        Local $sockaddr, $aRet, $aArray[4], $error
        $error = False
        $sockaddr = DllStructCreate("short;ushort;uint;char[8]")
        $aRet = DllCall($hDLL_WS2_32, "int", "getpeername", "int", $hSocket, _
                        "struct*", $sockaddr, "int*", DllStructGetSize($sockaddr))
        If @error Or $aRet[0] <> 0 Then
                $error = True
        Else
                $aRet = DllCall($hDLL_WS2_32, "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
                If Not @error Then $aArray[0] = $aRet[0]
                $aRet = DllCall($hDLL_WS2_32, "ushort", "ntohs", "ushort", DllStructGetData($sockaddr, 2))
                If Not @error Then $aArray[1] = $aRet[0]
        EndIf

        $aRet = DllCall($hDLL_WS2_32, "int", "getsockname", "int", $hSocket, _
                        "struct*", $sockaddr, "int*", DllStructGetSize($sockaddr))
        If @error Or $aRet[0] <> 0 Then
                $error = True
        Else
                $aRet = DllCall($hDLL_WS2_32, "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
                If Not @error Then $aArray[2] = $aRet[0]
                $aRet = DllCall($hDLL_WS2_32, "ushort", "ntohs", "ushort", DllStructGetData($sockaddr, 2))
                If Not @error Then $aArray[3] = $aRet[0]
        EndIf
        $sockaddr = 0
        Return SetError($error, False, $aArray)
EndFunc   ;==>_SocketToIP

Func _Selected()
        Local $Column, $Num, $iSocket
        $Column = _GUICtrlListView_GetSelectedCount($idListview)
        If $Column <> 1 Then Return
        $Num = _GUICtrlListView_GetSelectedIndices($idListview, False)
        _Echo($idEdit, "关闭连接" & $fd_Array[$Num][3])
        $iSocket = $fd_Array[$Num][1]
        TCPCloseSocket($iSocket)
        GUICtrlDelete($fd_Array[$Num][2])
        _FD_CLR($iSocket, $Client_Socket)
        _Array_CLR($iSocket, $fd_Array)
EndFunc   ;==>_Selected

Func _Selected_Send()
        Local $Column, $Num
        Local $aHotKey[1][2]
        $Column = _GUICtrlListView_GetSelectedCount($idListview)
        If $Column <> 1 Then Return
        $Num = _GUICtrlListView_GetSelectedIndices($idListview, False)
        $SendGUI = GUICreate("发送数据窗口", 600, 160, -1, -1, Default, Default, $hGUI)
        GUISetOnEvent($GUI_EVENT_CLOSE, "Close_GUI")
        $Button1 = GUICtrlCreateButton("发送", 260, 112, 85, 25)
        GUICtrlSetOnEvent($Button1, "_Button")
        $Input = GUICtrlCreateInput("", 32, 48, 520, 32)
        $aHotKey[0][0] = "{Enter}"
        $aHotKey[0][1] = $Button1
        GUISetAccelerators($aHotKey, $SendGUI)
        GUISetState(@SW_SHOW, $SendGUI)
        ControlFocus($SendGUI, "", $Input)
EndFunc   ;==>_Selected_Send

Func _Button()
        Local $Column, $iSocket, $iData, $Num
        $Column = _GUICtrlListView_GetSelectedCount($idListview)
        If $Column <> 1 Then Return
        $Num = _GUICtrlListView_GetSelectedIndices($idListview, False)
        $iData = GUICtrlRead($Input)
        $iSocket = $fd_Array[$Num][1]
        If $iData <> "" And $iSocket <> "" Then
                _Echo($idEdit, "发送消息" & $iData)
                _TCPSend($iSocket, $iData)
        EndIf
EndFunc   ;==>_Button

Func Close_GUI()
        GUISetAccelerators(0, $SendGUI)
        GUIDelete($SendGUI)
EndFunc   ;==>Close_GUI

Func _Exit()
        For $i = 0 To $TCP_MAX - 1
                TCPCloseSocket($TCP_Socket[$i])
        Next
        For $i = 0 To $FD_SETSIZE - 1
                If $fd_Array[$i][1] <> "" Then TCPCloseSocket($fd_Array[$i][1])
        Next
        UDPCloseSocket($UDP_Socket)
        DllClose($hDLL_WS2_32)
        TCPShutdown()
        Exit
EndFunc   ;==>_Exit

#Region DPI函数
Func _SetProcessDPIAware()
        Local $aRet
        If @OSBuild < 6000 Then Return ;判断系统版本 Windows Vista
        If @OSBuild < 9600 Then ;判断系统版本  win8.1(9600)
                $aRet = DllCall("User32.dll", "BOOL", "IsProcessDPIAware") ;检查进程是否支持DPI感知
                Return $aRet[0]
                If $aRet[0] = False Then
                        $aRet = DllCall('User32.dll', 'BOOL', 'SetProcessDPIAware') ;设置:系统DPI感知
                        If @error Then Return SetError(@error, 0, False)
                        Return
                EndIf
        Else
                $aRet = DllCall("Shcore.dll", "BOOL", "GetProcessDpiAwareness", "HWND", 0, "int*", 0) ;检查进程是否支持DPI感知
                If @error Then Return SetError(@error, 0, False)
                If $aRet[2] <> 2 Then ;0不支持DPI感知 1,系统DPI感知  2,监视器DPI感知
                        $aRet = DllCall("Shcore.dll", "BOOL", "SetProcessDpiAwareness", "int", 2) ;设置:监视器DPI感知
                        If @error Then Return SetError(@error, 0, False)
                        Return
                EndIf
        EndIf
EndFunc   ;==>_SetProcessDPIAware

Func _GetDpi()
        Local $iDPI
        If @OSBuild < 6000 Then Return 1 ;判断系统版本 Windows Vista
        If @OSBuild < 9600 Then ;判断系统版本  win8.1(9600)
                $iDPI = RegRead("HKCU\Control Panel\Desktop\WindowMetrics", "AppliedDPI")
        Else
                Local $hWnd = _WinAPI_MonitorFromWindow(_WinAPI_GetDesktopWindow())
                Local $aRet = DllCall("Shcore.dll", "BOOL", "GetDpiForMonitor", "HANDLE", $hWnd, "int", 0, "int*", 0, "int*", 0)
                If @error Then Return SetError(@error, 0, False)
                $iDPI = $aRet[3]
        EndIf
        If $iDPI < 96 Or $iDPI > 480 Then $iDPI = 96
        Return $iDPI / 96
EndFunc   ;==>_GetDpi

Func _IsProcessDPIAware()
        Local $aRet, $aDpi = 0
        If @OSBuild < 6000 Then Return False ;判断系统版本 Windows Vista
        If @OSBuild < 9600 Then ;判断系统版本  win8.1(9600)
                $aRet = DllCall("User32.dll", "BOOL", "IsProcessDPIAware") ;检查进程是否支持DPI感知
                If @error Then Return SetError(@error, 0, False)
                $aDpi = $aRet[0]
        Else
                $aRet = DllCall("Shcore.dll", "BOOL", "GetProcessDpiAwareness", "HWND", 0, "int*", 0) ;检查进程是否支持DPI感知
                If @error Then Return SetError(@error, 0, False)
                $aDpi = $aRet[2]
        EndIf
        Return $aDpi
EndFunc   ;==>_IsProcessDPIAware
#EndRegion DPI函数
 楼主| 发表于 2023-10-7 22:15:22 | 显示全部楼层
gyp2000 发表于 2023-10-7 21:09
以前写的 TCP服务端,你可以参考一下。

难道我要重写一个应对你这个服务端的客户端。老大,请将你的客户端代码一并发出,特别谢谢你
发表于 2023-10-7 22:30:43 | 显示全部楼层
wllx 发表于 2023-10-7 22:15
难道我要重写一个应对你这个服务端的客户端。老大,请将你的客户端代码一并发出,特别谢谢你

问题不在TCP呀。在于,【服】与【端】。

看你自己逻辑与想法吧。

 楼主| 发表于 2023-10-7 23:39:18 | 显示全部楼层
绿色风 发表于 2023-10-7 22:30
问题不在TCP呀。在于,【服】与【端】。

看你自己逻辑与想法吧。

老大,我真的想不出来,你能帮帮我吗?
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-2 04:37 , Processed in 0.082133 second(s), 15 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表