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

[网络通信] [以解决]我在论坛找的TCP通信例子,为什么打开发送端,接收端就会自己关闭呢?

[复制链接]
发表于 2019-2-1 15:43:57 | 显示全部楼层 |阅读模式
本帖最后由 aryce 于 2019-2-3 20:33 编辑

我在论坛找的TCP通信例子,为什么打开发送端,接收端就会自己关闭呢?第一次学习tcp通信, 希望大神能帮忙解答一下
版本3.3.9.21
系统win7x64

服务端:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $szIPADDRESS = "192.168.20.89";你的公共IP地址
Local $nPORT = 33891;端口
Local $MainSocket, $GOOEY, $edit, $ConnectedSocket, $szIP_Accepted
Local $msg, $recv

TCPStartup()
$MainSocket = TCPListen($szIPADDRESS, $nPORT)
$GOOEY = GUICreate("My Server (IP: " & $szIPADDRESS & ")", 300, 200)
$edit = GUICtrlCreateEdit("", 10, 10, 280, 180)
GUISetState()
$ConnectedSocket = -1
Do
        $ConnectedSocket = TCPAccept($MainSocket)
Until $ConnectedSocket <> -1

While 1
        $ConnectedSocket = TCPAccept($MainSocket)
        $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSE Then ExitLoop
        $recv = TCPRecv($ConnectedSocket, 2048)
        If @error Then ExitLoop
        If $recv <> "" Then GUICtrlSetData($edit, $recv & @CRLF & GUICtrlRead($edit))
;~                 If $ConnectedSocket <> -1 Then Exit
                
WEnd

If $ConnectedSocket <> -1 Then TCPCloseSocket($ConnectedSocket)
TCPShutdown()
客户端:
#Region ;**** 参数创建于 ACNWrapper_GUI ****
#PRE_Icon=C:\Windows\syswow64\SHELL32.dll
#PRE_UseX64=n
#PRE_Res_requestedExecutionLevel=None
#EndRegion ;**** 参数创建于 ACNWrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Local $ConnectedSocket, $szData
Local $szIPADDRESS = "192.168.20.89"
Local $nPORT = 33891
TCPStartup()
$ConnectedSocket = -1
$ConnectedSocket = TCPConnect($szIPADDRESS, $nPORT)
If @error Then
        MsgBox(4112, "错误", "TCP连接失败,服务端未启用!错误代码: " & @error)
Else
        While 1
                $szData = InputBox("发送数据给服务端", @LF & @LF & "输入一个要发送给服务端的数据:")
                If @error Or $szData = "" Then ExitLoop
                TCPSend($ConnectedSocket, $szData)
                If @error Then ExitLoop
        WEnd
EndIf



发表于 2019-2-1 16:28:29 | 显示全部楼层
本帖最后由 水木子 于 2019-2-1 16:37 编辑

新年快乐!
这东西我之前研究过,这是我之前练习写着玩的代码,代码都有注释,应该好理解,希望对你有点帮助吧!
为此我还专门写过一个聊天工具呢!


接收端:
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>

;~ 我是服务端,请先启动我。

TCPStartup() ; 启动 TCP 服务.

; 注册脚本关闭时调用的退出函数 OnAutoItExit().
OnAutoItExitRegister('OnAutoItExit')

; 分配局部变量回送 IP 地址和端口.
Global $sIPAddress = @IPAddress1 ; 此 IP 地址仅用于在您自己的计算机上测试.
Global $iPort = 65432 ; 用于连接的端口.

$hGui1 = GUICreate('服务端 (IP: ' & $sIPAddress & ')', 400, 300)
$Edit1 = GUICtrlCreateEdit('', 10, 10, 380, 280)
GUISetState()

_TCPServer_RecvData($sIPAddress, $iPort)

Func _TCPServer_RecvData($sIPAddress, $iPort)
        ; 分配一个局部变量套接字并绑定到的IP地址和端口, 指定最多 100 个挂起的联接.
        Local $iListenSocket = TCPListen($sIPAddress, $iPort, 100)
        Local $iError = 0
        Local Const $iMaxLen = 1024 * 1024

        If @error Then
                ; 可能有人已经在侦听此 IP 地址和端口(脚本已经在运行吗?).
                $iError = @error
                MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONHAND), '', '服务器:' & @CRLF & '不能接听, 错误代码: ' & $iError)
                Return False
        EndIf

        ; 指定客户端使用的套接字到本地变量.
        Local $iSocket = 0

        Do ; 等待有人来连接 (无限制).
                ; 接受存在的传入联接(完成时关闭套接字; 每个客户端一个套接字).
                $iSocket = TCPAccept($iListenSocket)

                ; 如果发生错误, 则显示错误代码, 并返回 False.
                If @error Then
                        $iError = @error
                        MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONHAND), '', '服务器:' & @CRLF & '不能接收传入的连接,错误代码: ' & $iError)
                        Return False
                EndIf
                
                If $iSocket <> -1 Then
                        $sReceived = TCPRecv($iSocket, $iMaxLen, 1)
                        If $sReceived <> '' Then GUICtrlSetData($Edit1, BinaryToString($sReceived, 4), 1)
                EndIf

        Until GUIGetMsg() = -3 ;如果不是 -1 则是一个客户端连接.

        ; 关闭侦听套接字允许之后绑定.
        TCPCloseSocket($iListenSocket)

        ; 关闭套接字.
        TCPCloseSocket($iSocket)
EndFunc   ;==>_TCPServer_RecvData

Func SocketToIP($iSocket)
        Local $tSockAddr, $aRet
        $tSockAddr = DllStructCreate('short;ushort;uint;char[8]')
        $aRet = DllCall('Ws2_32.dll', 'int', 'getpeername', 'int', $iSocket, 'struct*', $tSockAddr, 'int*', DllStructGetSize($tSockAddr))
        If Not @error And $aRet[0] = 0 Then
                $aRet = DllCall('Ws2_32.dll', 'str', 'inet_ntoa', 'int', DllStructGetData($tSockAddr, 3))
                If Not @error Then Return $aRet[0]
        EndIf
        Return 0
EndFunc   ;==>SocketToIP

Func OnAutoItExit()
        TCPShutdown() ; 关闭 TCP 服务.
EndFunc   ;==>OnAutoItExit


发送端:
#include <GuiIPAddress.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

;~ 我是客户端,请先启动服务端。
;~ ShellExecute(@ScriptDir & '\服务端.au3')

TCPStartup() ; 启动 TCP 服务.

; 注册脚本关闭时调用的退出函数 OnAutoItExit().
OnAutoItExitRegister('OnAutoItExit')

; 分配局部变量回送 IP 地址和端口.
Global $sIPAddress = @IPAddress1 ; 此 IP 地址仅用于在您自己的计算机上测试.
Global $iPort = 65432 ; 用于连接的端口.

$hGui1 = GUICreate('客户端 (IP: ' & $sIPAddress & ')', 400, 300)
$Edit1 = GUICtrlCreateEdit('', 10, 10, 380, 200)

GUICtrlCreateLabel('服务端IP:', 10, 230, 60, 17)
$IPAddress1 = _GUICtrlIpAddress_Create($hGui1, 70, 226, 130, 21)
_GUICtrlIpAddress_Set($IPAddress1, @IPAddress1)
GUICtrlCreateLabel(':', 210, 230, 10, 17)
$Input1 = GUICtrlCreateInput('65432', 225, 226, 60, 21)

GUICtrlCreateLabel('发送信息:', 10, 266, 60, 17)
$Input2 = GUICtrlCreateInput('', 70, 262, 240, 21)
$Button1 = GUICtrlCreateButton('发送', 310, 260, 80, 25)
GUISetState()

While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case -3
                        Exit
                Case $Button1
                        _TCP_SendData()

        EndSwitch
WEnd

Func _TCP_SendData()
        $sIPAddress = _GUICtrlIpAddress_Get($IPAddress1)
        $iPort = GUICtrlRead($Input1)
        $sData = GUICtrlRead($Input2)
        
        If $sData <> '' Then
                If $sIPAddress = '' Then $sIPAddress = @IPAddress1
                If $iPort = '' Then $iPort = 65432
                
                $sData = $sIPAddress & ' ' & @HOUR & ':' & @MIN & ':' & @SEC & @CRLF & $sData & @CRLF & @CRLF
                _TCPClient_SendData($sIPAddress, $iPort, $sData)
                GUICtrlSetData($Edit1, $sData, 1)
                GUICtrlSetData($Input2, '')
        EndIf
EndFunc   ;==>_TCP_SendData

Func _TCPClient_SendData($sIPAddress, $iPort, $sData)
        ; 分配本地变量一个套接字, 并连接到指定侦听套接字的 IP 地址与端口.
        Local $iSocket = TCPConnect($sIPAddress, $iPort)
        Local $iError = 0

        ; 如果发生错误, 则显示错误代码, 并返回 False.
        If @error Then
                ; 该服务器可能离线或未打开服务器的端口.
                $iError = @error
                MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONHAND), '', '客户端:' & @CRLF & '无法连接, 错误代码: ' & $iError)
                Return False
        EndIf

        TCPSend($iSocket, StringToBinary($sData, 4))

        ; 如果发生错误, 则显示错误代码, 并返回 False.
        If @error Then
                $iError = @error
                MsgBox(BitOR($MB_SYSTEMMODAL, $MB_ICONHAND), '', '客户端:' & @CRLF & '无法发送数据, 错误代码: ' & $iError)
                Return False
        EndIf

        ; 关闭套接字.
        TCPCloseSocket($iSocket)
EndFunc   ;==>_TCPClient_SendData

Func OnAutoItExit()
        TCPShutdown() ; 关闭 TCP 服务.
EndFunc   ;==>OnAutoItExit

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×

评分

参与人数 1金钱 +50 收起 理由
lpxx + 50 赞一个!

查看全部评分

 楼主| 发表于 2019-2-3 20:33:12 | 显示全部楼层
水木子 发表于 2019-2-1 16:28
新年快乐!
这东西我之前研究过,这是我之前练习写着玩的代码,代码都有注释,应该好理解,希望对你有点帮 ...

非常感谢啊 ~
发表于 2019-2-11 11:07:27 | 显示全部楼层
大过年的也在研究,辛苦了。
发表于 2019-2-16 15:35:10 | 显示全部楼层
研究下,辛苦了。有帮助!!!
发表于 2019-2-19 17:10:16 | 显示全部楼层
下载学习,支持分享!
发表于 2019-3-1 22:43:15 | 显示全部楼层
一起学习,谢谢分享
发表于 2019-3-9 16:34:56 | 显示全部楼层
看看怎么样。。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-4-23 20:41 , Processed in 0.081410 second(s), 22 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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