microsoft-visualbasic-runtime/Net/Tcp/TCPExtensions.vb

184 lines
7.3 KiB
VB.net
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#Region "Microsoft.VisualBasic::ac78e0e3b6b7dba2c2fa4a4acad57024, Microsoft.VisualBasic.Core\Net\Tcp\TCPExtensions.vb"
' Author:
'
' asuka (amethyst.asuka@gcmodeller.org)
' xie (genetics@smrucc.org)
' xieguigang (xie.guigang@live.com)
'
' Copyright (c) 2018 GPL3 Licensed
'
'
' GNU GENERAL PUBLIC LICENSE (GPL3)
'
'
' This program is free software: you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation, either version 3 of the License, or
' (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU General Public License for more details.
'
' You should have received a copy of the GNU General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
' /********************************************************************************/
' Summaries:
' Module TCPExtensions
'
' Function: ConnectSocket, GetFirstAvailablePort, (+2 Overloads) Ping, PortIsAvailable, PortIsUsed
'
'
' /********************************************************************************/
#End Region
Imports System.Net
Imports System.Net.NetworkInformation
Imports System.Net.Sockets
Imports System.Runtime.CompilerServices
Imports Microsoft.VisualBasic.Linq.Extensions
Imports Microsoft.VisualBasic.Net.Http
Imports Microsoft.VisualBasic.Net.Protocols
Namespace Net.Tcp
Public Module TCPExtensions
''' <summary>
''' -1标识Ping不通
''' </summary>
''' <param name="operationTimeOut">ms</param>
''' <returns></returns>
Public Function Ping(ep As System.Net.IPEndPoint, Optional operationTimeOut As Integer = 3 * 1000) As Double
Return New TcpRequest(ep).Ping(operationTimeOut)
End Function
''' <summary>
''' -1 ping failure
''' </summary>
''' <param name="invoke"></param>
''' <param name="timeout"></param>
''' <returns></returns>
<Extension>
Public Function Ping(invoke As TcpRequest, Optional timeout As Integer = 3 * 1000) As Double
Dim sw As Stopwatch = Stopwatch.StartNew
Dim request As RequestStream = RequestStream.SystemProtocol(RequestStream.Protocols.Ping, PING_REQUEST)
Dim response As RequestStream = invoke.SendMessage(request, timeout:=timeout)
If HTTP_RFC.RFC_REQUEST_TIMEOUT = response.Protocol Then
Return -1
End If
Return sw.ElapsedMilliseconds
End Function
Public Const PING_REQUEST As String = "PING/TTL-78973"
''' <summary>
''' 假若不能成功的建立起连接的话,则会抛出错误
''' </summary>
''' <param name="server"></param>
''' <param name="port"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function ConnectSocket(server As String, port As Integer) As System.Net.IPEndPoint
' Get host related information.
Dim HostEntry As IPHostEntry = Dns.GetHostEntry(server)
' Loop through the AddressList to obtain the supported AddressFamily. This is to avoid
' an exception that occurs when the host host IP Address is not compatible with the address family
' (typical in the IPv6 case).
For Each Address As IPAddress In HostEntry.AddressList
Dim endPoint As New System.Net.IPEndPoint(Address, port)
Dim Socket As Socket = New Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp)
Try
Call Socket.Connect(endPoint)
Catch ex As Exception
Continue For
End Try
If Socket.Connected Then
Return endPoint
End If
Next
Throw New Exception(String.Format("The target connection to {0}:{1} can not be made!", server, port))
End Function
Const MAX_PORT As Integer = 65535 '系统tcp/udp端口数最大是65535
''' <summary>
''' Get the first available TCP port on this local machine.
''' (获取第一个可用的端口号,请注意,在高并发状态下可能会出现端口被占用的情况,
''' 所以这时候建议将<paramref name="BEGIN_PORT"/>设置为-1则本函数将会尝试使用随机数来分配可用端口从而避免一些系统崩溃的情况产生)
''' </summary>
''' <param name="BEGIN_PORT">Check the local port available from this port value.(从这个端口开始检测)</param>
''' <returns></returns>
Public Function GetFirstAvailablePort(Optional BEGIN_PORT As Integer = 100) As Integer
If BEGIN_PORT <= 0 Then
BEGIN_PORT = Rnd() * (MAX_PORT - 1) ' 为了避免高并发的时候出现端口占用的情况,在这里使用随机数来解决一些问题
End If
For i As Integer = BEGIN_PORT To MAX_PORT - 1
If PortIsAvailable(port:=i) Then
Return i
End If
Next
Return -1
End Function
''' <summary>
''' 获取操作系统已用的端口号
''' </summary>
''' <returns></returns>
Public Function PortIsUsed() As Integer()
'获取本地计算机的网络连接和通信统计数据的信息
Dim ipGlobalProperties__1 As IPGlobalProperties = IPGlobalProperties.GetIPGlobalProperties()
'返回本地计算机上的所有Tcp监听程序
Dim ipsTCP As System.Net.IPEndPoint() = ipGlobalProperties__1.GetActiveTcpListeners()
'返回本地计算机上的所有UDP监听程序
Dim ipsUDP As System.Net.IPEndPoint() = ipGlobalProperties__1.GetActiveUdpListeners()
'返回本地计算机上的Internet协议版本4(IPV4 传输控制协议(TCP)连接的信息。
Dim tcpConnInfoArray As TcpConnectionInformation() = ipGlobalProperties__1.GetActiveTcpConnections()
Dim allPorts As List(Of Integer) = New List(Of Integer)
Call allPorts.AddRange((From ep As System.Net.IPEndPoint In ipsTCP Select ep.Port).ToArray)
Call allPorts.AddRange((From ep As System.Net.IPEndPoint In ipsUDP Select ep.Port).ToArray)
Call allPorts.AddRange((From conn As TcpConnectionInformation In tcpConnInfoArray Select conn.LocalEndPoint.Port).ToArray)
Return allPorts.ToArray
End Function
''' <summary>
''' 检查指定端口是否已用
''' </summary>
''' <param name="port"></param>
''' <returns></returns>
Public Function PortIsAvailable(port As Integer) As Boolean
Dim portUsed As Integer() = PortIsUsed()
For Each p As Integer In portUsed
If p = port Then
Return False
End If
Next
Return True
End Function
End Module
End Namespace