破帽遮颜 发表于 2010-7-30 08:22:37

创建TCP连接时,系统自动分配的端口,怎么样获取这个端口呢

本帖最后由 破帽遮颜 于 2010-8-1 14:56 编辑

创建TCP连接,端口号为0时,系统会自动分配一个空闲端口,使用什么方法可以获取这个端口号呢?

getsockname?

悬赏贴http://www.autoitx.com/thread-17303-1-1.html#include 'array.au3'

TCPStartup()
Global Const $__TCP_WINDOW = GUICreate('')
Global $hWs2_32 = -1


_TCP_Server_Create(0, '0.0.0.0')
MsgBox(4096, '', '现在服务端创建的TCP连接使用的端口是?该如何获取呢?')

While 1
        Sleep(100)
WEnd


Func _TCP_Server_Create($iPort, $sIP = "0.0.0.0")
        $hListenSocket = _ASocket()
        _ASockSelect($hListenSocket, $__TCP_WINDOW, 0x0400, 8)
        _ASockListen($hListenSocket, $sIP, $iPort)
        Return $hListenSocket
EndFunc   ;==>_TCP_Server_Create

Func _ASocket($iAddressFamily = 2, $iType = 1, $iProtocol = 6)
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        Local $hSocket = DllCall($hWs2_32, "uint", "socket", "int", $iAddressFamily, "int", $iType, "int", $iProtocol)
        If @error Then
                SetError(1, @error)
                Return -1
        EndIf
        If $hSocket = -1 Then
                SetError(2, _WSAGetLastError())
                Return -1
        EndIf
        Return $hSocket
EndFunc   ;==>_ASocket

Func _ASockSelect($hSocket, $hWnd, $uiMsg, $iEvent)
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        Local $iRet = DllCall($hWs2_32, "int", "WSAAsyncSelect", "uint", $hSocket, "hwnd", $hWnd, "uint", $uiMsg, "int", $iEvent)
        If @error Then
                SetError(1, @error)
                Return False
        EndIf
        Return True
EndFunc   ;==>_ASockSelect

Func _ASockListen($hSocket, $sIP, $uiPort, $iMaxPending = 5)
        Local $iRet
        Local $stAddress
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        $stAddress = __SockAddr($sIP, $uiPort)
        If @error Then
                SetError(@error, @extended)
                Return False
        EndIf

        $iRet = DllCall($hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($stAddress), "int", DllStructGetSize($stAddress))
        If @error Then
                SetError(3, @error)
                Return False
        EndIf
        If $iRet <> 0 Then
                $stAddress = 0
                SetError(4, _WSAGetLastError())
                Return False
        EndIf

        $iRet = DllCall($hWs2_32, "int", "listen", "uint", $hSocket, "int", $iMaxPending)
        If @error Then
                SetError(5, @error)
                Return False
        EndIf
        If $iRet <> 0 Then
                $stAddress = 0
                SetError(6, _WSAGetLastError())
                Return False
        EndIf
        Return True
EndFunc   ;==>_ASockListen

Func __SockAddr($sIP, $iPort, $iAddressFamily = 2)
        Local $iRet
        Local $stAddress
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        $stAddress = DllStructCreate("short;ushort;uint;char")
        If @error Then
                SetError(1, @error)
                Return False
        EndIf
        DllStructSetData($stAddress, 1, $iAddressFamily)
        $iRet = DllCall($hWs2_32, "ushort", "htons", "ushort", $iPort)
        DllStructSetData($stAddress, 2, $iRet)
        $iRet = DllCall($hWs2_32, "uint", "inet_addr", "str", $sIP)
        If $iRet = 0xffffffff Then
                $stAddress = 0
                SetError(2, _WSAGetLastError())
                Return False
        EndIf
        DllStructSetData($stAddress, 3, $iRet)
        Return $stAddress
EndFunc   ;==>__SockAddr

Func _WSAGetLastError()
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        Local $iRet = DllCall($hWs2_32, "int", "WSAGetLastError")
        If @error Then
                ConsoleWrite("+> _WSAGetLastError(): WSAGetLastError() failed. Script line number: " & @ScriptLineNumber & @CRLF)
                SetExtended(1)
                Return 0
        EndIf
        Return $iRet
EndFunc   ;==>_WSAGetLastError

破帽遮颜 发表于 2010-7-30 08:24:38

希望有高手指点

破帽遮颜 发表于 2010-7-30 19:57:43

Up~~~~~~~~~~~~~~~~~~~~~

auto 发表于 2010-7-30 23:16:30

能指定端口吗,
我试过UDP发送数据,可以指定远程的端口号,但不能指定本地发送数据的端口号

破帽遮颜 发表于 2010-7-31 00:40:45

能指定端口吗,
我试过UDP发送数据,可以指定远程的端口号,但不能指定本地发送数据的端口号
auto 发表于 2010-7-30 23:16 http://www.autoitx.com/images/common/back.gif

指定端口就失去这个问题的意义了。
呵呵

ceoguang 发表于 2010-7-31 03:00:48

先具体解释下端口为0是怎样?
你所说的TCP连接是指TCPListen?TCPConnect?
or???

破帽遮颜 发表于 2010-7-31 08:46:48

本帖最后由 破帽遮颜 于 2010-8-1 14:52 编辑

#include 'array.au3'

TCPStartup()
Global Const $__TCP_WINDOW = GUICreate('')
Global $hWs2_32 = -1


_TCP_Server_Create(0, '0.0.0.0')
MsgBox(4096, '', '现在服务端创建的TCP连接使用的端口是?该如何获取呢?')

While 1
        Sleep(100)
WEnd


Func _TCP_Server_Create($iPort, $sIP = "0.0.0.0")
        $hListenSocket = _ASocket()
        _ASockSelect($hListenSocket, $__TCP_WINDOW, 0x0400, 8)
        _ASockListen($hListenSocket, $sIP, $iPort)
        Return $hListenSocket
EndFunc   ;==>_TCP_Server_Create

Func _ASocket($iAddressFamily = 2, $iType = 1, $iProtocol = 6)
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        Local $hSocket = DllCall($hWs2_32, "uint", "socket", "int", $iAddressFamily, "int", $iType, "int", $iProtocol)
        If @error Then
                SetError(1, @error)
                Return -1
        EndIf
        If $hSocket = -1 Then
                SetError(2, _WSAGetLastError())
                Return -1
        EndIf
        Return $hSocket
EndFunc   ;==>_ASocket

Func _ASockSelect($hSocket, $hWnd, $uiMsg, $iEvent)
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        Local $iRet = DllCall($hWs2_32, "int", "WSAAsyncSelect", "uint", $hSocket, "hwnd", $hWnd, "uint", $uiMsg, "int", $iEvent)
        If @error Then
                SetError(1, @error)
                Return False
        EndIf
        Return True
EndFunc   ;==>_ASockSelect

Func _ASockListen($hSocket, $sIP, $uiPort, $iMaxPending = 5)
        Local $iRet
        Local $stAddress
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        $stAddress = __SockAddr($sIP, $uiPort)
        If @error Then
                SetError(@error, @extended)
                Return False
        EndIf

        $iRet = DllCall($hWs2_32, "int", "bind", "uint", $hSocket, "ptr", DllStructGetPtr($stAddress), "int", DllStructGetSize($stAddress))
        If @error Then
                SetError(3, @error)
                Return False
        EndIf
        If $iRet <> 0 Then
                $stAddress = 0
                SetError(4, _WSAGetLastError())
                Return False
        EndIf

        $iRet = DllCall($hWs2_32, "int", "listen", "uint", $hSocket, "int", $iMaxPending)
        If @error Then
                SetError(5, @error)
                Return False
        EndIf
        If $iRet <> 0 Then
                $stAddress = 0
                SetError(6, _WSAGetLastError())
                Return False
        EndIf
        Return True
EndFunc   ;==>_ASockListen

Func __SockAddr($sIP, $iPort, $iAddressFamily = 2)
        Local $iRet
        Local $stAddress
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        $stAddress = DllStructCreate("short;ushort;uint;char")
        If @error Then
                SetError(1, @error)
                Return False
        EndIf
        DllStructSetData($stAddress, 1, $iAddressFamily)
        $iRet = DllCall($hWs2_32, "ushort", "htons", "ushort", $iPort)
        DllStructSetData($stAddress, 2, $iRet)
        $iRet = DllCall($hWs2_32, "uint", "inet_addr", "str", $sIP)
        If $iRet = 0xffffffff Then
                $stAddress = 0
                SetError(2, _WSAGetLastError())
                Return False
        EndIf
        DllStructSetData($stAddress, 3, $iRet)
        Return $stAddress
EndFunc   ;==>__SockAddr

Func _WSAGetLastError()
        If $hWs2_32 = -1 Then $hWs2_32 = DllOpen("Ws2_32.dll")
        Local $iRet = DllCall($hWs2_32, "int", "WSAGetLastError")
        If @error Then
                ConsoleWrite("+> _WSAGetLastError(): WSAGetLastError() failed. Script line number: " & @ScriptLineNumber & @CRLF)
                SetExtended(1)
                Return 0
        EndIf
        Return $iRet
EndFunc   ;==>_WSAGetLastError

0633zhou 发表于 2010-7-31 09:04:00

帮顶下,太深奥了

akmm88 发表于 2010-7-31 09:48:33

开始监听或者连接后,你你设置的0 在读出来,就可以得到系统赋予的端口号.
getsockname(........)
$stAddress里的htons

akmm88 发表于 2010-7-31 10:15:43

_MakeLong 为什么不用位移 *10000和左移4位,效率应该不同.

没有线程池甚至连工作线程都没有.
你就没有试试启动1000个客户端.
CONNECT后立即CLOSE,你的服务端还能正常工作吗?
redim的效率非常低,而且内存泄漏严重.
这种方法可能导致服务端不能正常长时间运行.
      $iRet = _WSAGetLastError()
      If $iRet = 10035 Then
                Return True
      EndIf
      SetExtended(1)
      Return True
这段更让人看不懂.
既然WSAGetLastError不等于0也不等于WSAEISCONN (10056) ,顶多也只能说明正在连接中.
没看到有设置CONNECT超时,那么你CONN时,是不是整个程序就要等待6秒左右的无法响应?(如果IP不存在.)


仅提下建议,别介意. 其实我很想看到牛人,能用AU3这种单线程 写出 SOCKET服务,所以说了这么多.

auto 发表于 2010-7-31 10:22:07

指定端口就失去这个问题的意义了。
呵呵
破帽遮颜 发表于 2010-7-31 00:40 http://www.autoitx.com/images/common/back.gif

是我刚好有这个需求,需要指端口来发送数据

wsfda 发表于 2010-7-31 10:30:18

深奥,还未接触,,,,加油,努力

破帽遮颜 发表于 2010-7-31 17:31:23

_MakeLong 为什么不用位移 *10000和左移4位,效率应该不同.

没有线程池甚至连工作线程都没有.
你就没有试 ...
akmm88 发表于 2010-7-31 10:15 http://www.autoitx.com/images/common/back.gif


呵呵,谢谢回复。
这个UDF并不是我写的。我只是针对系统随机分配端口,所以放上来一个例子。
你能帮忙解决这个问题吗?拜托了。^_^

republican 发表于 2010-7-31 17:52:53

回复 7# 破帽遮颜

这个很漂亮~~

C.L 发表于 2010-7-31 17:53:58

没弄明白,要获取的是sever的端口,还是Client的端口?
页: [1] 2
查看完整版本: 创建TCP连接时,系统自动分配的端口,怎么样获取这个端口呢