找回密码
 加入
搜索
查看: 5750|回复: 7

[网络通信] TCP发送信息,服务端添加ListView鼠标事件后,客户端接收不到(已解决)

  [复制链接]
发表于 2012-9-19 22:55:49 | 显示全部楼层 |阅读模式
本帖最后由 夜猫猫 于 2012-9-23 14:45 编辑

原码是网管联盟ThinKing的列子
服务端
#Region ;**** 参数创建于 ACNWrapper_GUI ****
#AutoIt3Wrapper_icon=include\Ser.ico
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <WindowsConstants.au3>
#include <array.au3>
#include <EditConstants.au3>

;~ #include <ListViewConstants.au3>
#include <GuiListView.au3>

Opt("GUIOnEventMode", 1) ;GUIi事件模式

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("服务端", 456, 309 + 150 + 30, 315, 196)
;GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ;去掉此调用客户端能正常接收
GUISetOnEvent($GUI_EVENT_CLOSE, "_gui")
$ListView1 = GUICtrlCreateListView("socket|IP", 8, 8, 442, 286, 0x0008)
$Edit1 = GUICtrlCreateEdit("", 8, 300, 220, 150, BitOR($ES_WANTRETURN, $WS_VSCROLL))
$Edit2 = GUICtrlCreateEdit("", 8 + 220, 300, 220, 150, BitOR($ES_WANTRETURN, $WS_VSCROLL))

$listmenu1 = GUICtrlCreateContextMenu($ListView1);给一个控件建上下文菜单(右键菜单)
$menu1 = GUICtrlCreateMenuItem("发送", $listmenu1)
GUICtrlSetOnEvent(-1, "_gui")

$button1 = GUICtrlCreateButton("array", 8, 309 + 150 + 30 - 30)
GUICtrlSetOnEvent(-1, "_gui")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###


Global $szIPADDRESS = @IPAddress1 ;你的公共IP地址
Global $nPORT = 33892;端口
Global $MainSocket, $GOOEY, $edit, $ConnectedSocket, $szIP_Accepted
Global $msg, $recv
Global $OnlineList[1][2] ;在线列表

; 开始 TCP 服务
;==============================================
TCPStartup()
$ConnectedSocket = -1
$MainSocket = TCPListen($szIPADDRESS, $nPORT)
If $MainSocket = -1 Then
        MsgBox(64,"提示","创建监听失败,程序无法运行,请重新设置端口")
        Exit
EndIf


AdlibRegister("_ReduceMemory", 1000 * 10) ;10秒整理一次内存
AdlibRegister("_AcceptAndDelList") ;默认250MS检测一次是否有新客户机连接与删除旧客户机


_ReduceMemory()

While 1
        Sleep(1000)
WEnd

Func _Gui()
        Switch @GUI_CtrlId
                Case $GUI_EVENT_CLOSE
                        Exit
                Case $button1
                        _ArrayDisplay($OnlineList)
                Case $menu1
                        $Tinput = InputBox("请输入数据", "")
                        If Not @error Then
                                _SendText($Tinput)
                        EndIf
        EndSwitch
EndFunc   ;==>_Gui
Func _SendText($Text);将数据转换成二进制再发送
        $totalnum = _GUICtrlListView_GetItemCount($ListView1)
        $selectcount = _GUICtrlListView_GetSelectedCount($ListView1)
        $out = ""
        For $i = 0 To $totalnum - 1
                If $selectcount Then
                        If _GUICtrlListView_GetItemSelected($ListView1, $i) == True Then
                                $Lsocket = _GUICtrlListView_GetItemText($ListView1, $i, 0)
                                TCPSend($Lsocket, StringToBinary("Control_Msg|" & $Text, 4))
;~                         TCPSend($Lsocket, StringToBinary("Control_Msg|" & $Text, 4))
;~                         MsgBox(0,0,$Lsocket)
                        EndIf
                Else
;~           $out = "没有选择文件"
                EndIf
        Next
EndFunc   ;==>_SendText

Func _AcceptAndDelList();定时接受与删除列表
        $begin = TimerInit()
        AdlibUnRegister("_AcceptAndDelList")
        _Accept();接受新客户机
        _Recv_Dellist();删除离线的客户机
        AdlibRegister("_AcceptAndDelList")
        GUICtrlSetData($Edit1, Round(TimerDiff($begin), 3) & " MS" & @CRLF, "|")
EndFunc   ;==>_AcceptAndDelList

Func _Accept() ;接受新客户端连接,并维护socket表
        $ConnectedSocket = TCPAccept($MainSocket)
        If $ConnectedSocket <> -1 Then ;<>-1表示有新客户端连接
                $szIP_Accepted = SocketToIP($ConnectedSocket) ;socket转成
                $all = UBound($OnlineList) + 1
                ReDim $OnlineList[$all][2] ;在线列表数组增加
                $OnlineList[$all - 1][0] = $ConnectedSocket ;socket
                $OnlineList[$all - 1][1] = $szIP_Accepted ;ip
                WinSetTitle($Form1, "", "服务端,共在线:" & UBound($OnlineList) - 1 & " 台机子")
                GUICtrlCreateListViewItem($OnlineList[$all - 1][0] & "|" & $OnlineList[$all - 1][1], $ListView1)
                GUICtrlSetData($Edit2, $szIP_Accepted & " 上线 - " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF, "|")
        EndIf
EndFunc   ;==>_Accept

Func _Recv_Dellist() ;接收客户机发来数据并删除关闭的socket列表
        For $i = 1 To UBound($OnlineList) - 1
;~                 $recv = TCPsend($OnlineList[$i][0], "") ;废时间
                $recv = TCPSend($OnlineList[$i][0], 10)
                If @error Then
                        ;搜索LISTVIEW中需要离线的,并删除
                        $a = ControlListView($Form1, "", $ListView1, "FindItem", $OnlineList[$i][0]) ;获取GUI上的socket的listview的行
                        $Del_ip = _GUICtrlListView_GetItemText($ListView1, $a, 1) ;获取要删的列的IP
                        _GUICtrlListView_DeleteItem($ListView1, $a);删除
                        ;显示离线
                        GUICtrlSetData($Edit2, $Del_ip & " 离线 - " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF, "|")
                        ;删除数组
                        _ArrayDelete($OnlineList, $i)
                        WinSetTitle($Form1, "", "服务端,共在线:" & UBound($OnlineList) - 1 & " 台机子")
                        AdlibRegister("_Recv_Dellist");重新启用
                        ExitLoop ;这个退出用来防止删除过多的socket,如果没有这个可能导致 $recv = TCPRecv($OnlineList[$i][0], "") 这一句数组错误。
                EndIf
        Next
        
EndFunc   ;==>_Recv_Dellist

Func SocketToIP($SHOCKET)
        Local $sockaddr, $aRet
        $sockaddr = DllStructCreate("short;ushort;uint;char[8]")
        $aRet = DllCall("Ws2_32.dll", "int", "getpeername", "int", $SHOCKET, _
                        "ptr", DllStructGetPtr($sockaddr), "int*", DllStructGetSize($sockaddr))
        If Not @error And $aRet[0] = 0 Then
                $aRet = DllCall("Ws2_32.dll", "str", "inet_ntoa", "int", DllStructGetData($sockaddr, 3))
                If Not @error Then $aRet = $aRet[0]
        Else
                $aRet = 0
        EndIf
        $sockaddr = 0
        Return $aRet
EndFunc   ;==>SocketToIP


Func _ReduceMemory()
        $I_PID = @AutoItPID
        Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $I_PID)
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
        DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
        Return $ai_Return[0]
EndFunc   ;==>_ReduceMemory

Func WM_NOTIFY($hWndGUI, $MsgID, $wParam, $lParam)
Local $tagNMHDR, $event, $hwndFrom, $code
$tagNMHDR = DllStructCreate("int;int;int", $lParam)
If @error Then Return
$event = DllStructGetData($tagNMHDR, 3)
If $wParam = $ListView1 And $event = $NM_RCLICK Then
IF _GUICtrlListView_GetSelectedIndices($ListView1) = "" Then
      GUICtrlSetState ($menu1, $GUI_DISABLE)
   Else
      GUICtrlSetState ($menu1, $GUI_ENABLE)
   Endif
Endif
$tagNMHDR = 0
$event = 0
$lParam = 0
EndFunc  ;==> 在$ListView1中鼠标事件
客户端
#notrayicon
; 设置一些常用信息
;--------------------------
Local $ConnectedSocket, $szData
; 设置 $szIPADDRESS 为服务端IP. 这里使用本地的机器名称转换为 IP 地址
;   Local $szServerPC = @ComputerName
;   Local $szIPADDRESS = TCPNameToIP($szServerPC)
Local $szIPADDRESS =@IPAddress1
Local $nPORT = 33892

; 开始 TCP 服务
;==============================================
TCPStartup()

; 初始化一个变量描述连接
;==============================================
$ConnectedSocket = -1

;尝试连接到服务端IP的 33891 端口.
;=======================================================


While 1
        ToolTip($ConnectedSocket & " - 服务端在线,空闲等待接收数据...", 10, 10)
        _Recv()
        Sleep(300)
WEnd

Func _Recv()
        $recv = TCPRecv($ConnectedSocket, 1024 * 50, 1)
        If @error Then
                _Conn()
                Return 0
        ElseIf $recv <> "" Then;如果接收不为空
                $recv = BinaryToString($recv, 4)
                $recv = StringSplit($recv, "|")
                If $recv[1] = "Control_Msg" Then
                        tooltip($recv[2],10,30)
                        Msgbox(0,0,$recv[2])
                EndIf                
        EndIf
EndFunc   ;==>_Recv

Func _Conn()
        ToolTip($ConnectedSocket & " - 服务端离线,等待偿试连接中...", 10, 10)
        $ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)
EndFunc   ;==>_Conn
发表于 2012-9-20 10:10:19 | 显示全部楼层
支持一下...
 楼主| 发表于 2012-9-20 19:02:03 | 显示全部楼层
这个是深蓝修正的
sliqi 发表于 2012-9-20 08:53


我发的也是这个
不过我添加LISTVIEW鼠标焦点事件后,客户端就不能正常接收了。。
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

Func WM_NOTIFY($hWndGUI, $MsgID, $wParam, $lParam)
Local $tagNMHDR, $event, $hwndFrom, $code
$tagNMHDR = DllStructCreate("int;int;int", $lParam)
If @error Then Return
$event = DllStructGetData($tagNMHDR, 3)
If $wParam = $ListView1 And $event = $NM_RCLICK Then
IF _GUICtrlListView_GetSelectedIndices($ListView1) = "" Then
      GUICtrlSetState ($menu1, $GUI_DISABLE)
   Else
      GUICtrlSetState ($menu1, $GUI_ENABLE)
   Endif
Endif
$tagNMHDR = 0
$event = 0
$lParam = 0
EndFunc  ;==> 在$ListView1中鼠标事件
 楼主| 发表于 2012-9-23 14:43:44 | 显示全部楼层
刚抓包看了一下,是由于服务端发包所出现的问题,造成客户端有时收到有时收不到
服务端修改117行
$recv = ...
sliqi 发表于 2012-9-21 10:34



是不是让心包跳加上指定字符发送以区别?

谢谢,问题解决。请问用什么工具抓包。能说下吗?
发表于 2012-12-5 10:25:59 | 显示全部楼层
发表于 2013-5-1 16:25:54 | 显示全部楼层
学习一下,谢谢分享
发表于 2013-8-6 21:07:05 | 显示全部楼层
支持一下...
发表于 2013-12-27 05:06:31 | 显示全部楼层
支持一下...
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-6-1 19:30 , Processed in 0.082496 second(s), 23 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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