为什么要在做这个?
PowerShell 进行 TCP 通信可以在许多场景中发挥作用,包括但不限于以下几个方面:
- 网络服务监控和管理:通过 PowerShell,你可以编写脚本来检查服务器上的网络服务是否可用,例如检查某个端口是否打开、某个服务是否正在运行等。这对于监控和管理网络服务的健康状态非常有用。
- 远程服务器管理:PowerShell 提供了与远程计算机进行通信的功能,包括通过 TCP 连接执行命令和脚本。这使得你可以远程管理服务器、执行远程命令、获取远程计算机的信息等。
- 自动化任务和脚本:通过 PowerShell 的 TCP 通信功能,你可以编写脚本来执行各种自动化任务,如与网络设备进行通信、与 Web 服务进行交互、与其他应用程序进行数据交换等。这对于自动化任务和脚本编写非常有帮助。
- 网络编程和测试:如果你对网络编程感兴趣,PowerShell 提供了一些功能来进行 TCP 通信,可以用于编写网络应用程序或进行网络测试。你可以使用 PowerShell 创建 TCP 客户端和服务器,发送和接收数据,模拟网络通信等。
方法1:使用.NET Framework提供的类库来实现TCP通信
在PowerShell中,可以使用.NET Framework提供的类库来实现TCP通信。下面是一个简单的示例,展示了如何在PowerShell中使用System.Net.Sockets命名空间中的类来建立TCP连接、发送和接收数据:
$tcpClientType = @"
using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
public class TcpClientExample
{
public void Run()
{
// 服务器IP和端口
string serverIP = "127.0.0.1";
int serverPort = 12345;
// 创建TCP客户端
TcpClient client = new TcpClient();
try
{
// 连接服务器
client.Connect(serverIP, serverPort);
// 获取网络流
NetworkStream stream = client.GetStream();
// 发送数据
string message = "Hello, server!";
byte[] data = Encoding.ASCII.GetBytes(message);
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: " + message);
// 接收数据
data = new byte[1024];
int bytesRead = stream.Read(data, 0, data.Length);
string response = Encoding.ASCII.GetString(data, 0, bytesRead);
Console.WriteLine("Received: " + response);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
finally
{
// 关闭连接
client.Close();
}
}
}
"@
# 编译类型定义为程序集
Add-Type -TypeDefinition $tcpClientType
# 创建对象并调用自定义方法
$tcpClient = New-Object -TypeName TcpClientExample
$tcpClient.Run()在这个示例中,我们使用了Add-Type命令来将一段C#代码添加到PowerShell会话中。这段C#代码定义了一个名为TcpClientExample的类,其中包含一个Main方法。这个类的目的是建立TCP连接、发送数据并接收服务器的响应。
在PowerShell中,我们首先使用Add-Type命令来将C#代码添加到会话中。然后,我们使用New-Object命令创建了一个TcpClientExample对象,并将其存储在$tcpClient变量中。接下来,我们调用$tcpClient对象的Main方法。
在Main方法中,我们首先指定要连接的服务器的IP地址和端口号。然后,我们创建了一个TcpClient对象,该对象用于建立与服务器的TCP连接。接着,我们获取与服务器的连接的网络流(NetworkStream),这样我们就可以通过流发送和接收数据。
在示例中,我们发送了一条消息("Hello, server!")到服务器。我们将消息转换为字节数组,并使用网络流的Write方法将数据发送给服务器。
然后,我们准备接收服务器的响应。我们创建一个字节数组来存储接收到的数据,并使用网络流的Read方法从服务器接收数据。我们将接收到的字节数组转换为字符串,并将其打印到控制台。
最后,我们使用TcpClient对象的Close方法关闭与服务器的连接。
但是这样实现对于运维同学来说还是显得复杂了些。
方法2:简化版使用.NET Framework提供的类库来实现TCP通信
原理与代码
要在 PowerShell 中实现 TCP 通信,你需要借助 .NET Framework 中的类库来完成。在 .NET Framework 中,有一些用于 TCP 通信的类,如 System.Net.Sockets.TcpClient 和 System.Net.Sockets.TcpListener。你可以使用这些类来创建 TCP 客户端和服务器,并进行数据的发送和接收。
服务器端代码:
# TCP 服务器
# 创建侦听
$port = 12345
$listener = New-Object System.Net.Sockets.TcpListener([System.Net.IPAddress]::Any, $port) # 创建TCP侦听
$listener.Start() # 启动侦听
$tcpClient = $listener.AcceptTcpClient() # 等待 客户端建立连接后才会继续
$stream = $tcpClient.GetStream()
$buffer = New-Object byte[] 1024
$bytesRead = $stream.Read($buffer, 0, $buffer.Length) # 等待 客户端在stream中write数据后才会继续
$datafromclient = [System.Text.Encoding]::ASCII.GetString($buffer, 0, $bytesRead) #byte to string
Write-Host $datafromclient
$stream.Write([System.Text.Encoding]::ASCII.GetBytes("Hello, client!"), 0, 14) # 将要发送到Cliet的byte流写进stream
$stream.Close()
$tcpClient.Close()
$listener.Stop()客户端代码
# TCP 客户端
# 建立连接
$serverip = "192.168.11.199"
$port = 12345
$tcpClient = New-Object System.Net.Sockets.TcpClient
$tcpClient.Connect($serverip, $port)
$stream = $tcpClient.GetStream() # 获取流
$buffer = [System.Text.Encoding]::ASCII.GetBytes("Hello, server!") # 将要发送的数据转变为Byte
$stream.Write($buffer, 0, $buffer.Length) #将byte流写进stream
$buffer = New-Object byte[] 1024 # 创建buffer
$bytesRead = $stream.Read($buffer, 0, $buffer.Length) # 等待 当服务端将数据write到stream中之后才会继续;将stream中的byte读出来,读取长度是buffer的长度
$datafromserver = [System.Text.Encoding]::ASCII.GetString($buffer, 0, $bytesRead) # 将从stream中读取的的byte转换成string
Write-Host $datafromserver
$stream.Close() # 关闭stream
$tcpClient.Close() # 关闭连接之前提供的示例与这个示例是相同的。这个示例展示了如何使用 .NET Framework 类库在 PowerShell 中实现基本的 TCP 通信。
这个示例中,我们创建了一个 TCP 服务器和一个 TCP 客户端。服务器监听本地 IP 地址的 12345 端口,并接受传入的连接。客户端连接到服务器的 IP 地址和端口。
服务器首先接受客户端的连接,并获取与客户端通信的网络流($stream)。然后,服务器从流中读取数据,并将读取到的数据发送回客户端。
客户端连接到服务器,并获取与服务器通信的网络流($stream)。然后,客户端将数据发送到服务器,并从流中读取服务器发送的响应数据。
这个示例是一个简化的演示,用于展示如何使用 .NET Framework 类库在 PowerShell 中实现 TCP 通信。
执行演示
首先确定服务器的IP及端口使用情况

在服务器端侦听端口,并确认端口已处与侦听状态

在客户端验证下端口的连通性

证明可以连通

此时 在服务器上也可以看到客户但与服务器的端口连接已经处于ESTABLISHED状态了

如果您看本文只是为了测试客户端和服务器端的端口连通情况,到这里就可以了。
在服务器端接收Client的数据

此时在客户端上与服务器建立TCP连接

此时服务器的等待状态就会发生改变

顺便在服务器端检测下连接状况

服务器端继续执行GetStream()并从stream中获取byte流

在客户端上执行GetStream()并向stream中写入byte流

此时服务器端的状态就会自动发生变化,并获取到客户端发来的数据Hello Server!

我们在从服务器端向stream中写入数据

然后在客户端接收数据

最后分别再服务器和客户端上关闭stream、client以及listener


补充:客户端和服务器端的发生和接收操作并不是死板的一发一收;而是双方都可以连续多次发送,而接收方则可以在发送方多次发送后一次性地从stream中取出数据。
我为什么些这篇文章呢?因为再最近的项目实施的过程中出现一个问题,服务器的端口明明是开放访问的且没有任何异常;但是同网段的其他服务器就是无法访问这个端口,其他端口有的正常有的不正常;那么肯定是怀疑环境中存在安全软件或装置进行了阻止,但是用户那边坚持说没有阻止访问;那我们就想到把我们的服务器程序先停止释放端口,然后使用powershell侦听这个端口,然后测试该端口是否可以访问;凭此来反证环境中存在未知的安全装置。
为什么不用现成的工具呢?一来好用的工具少,二来生产环境安全要求较高也担心小工具会有安全风险;既然powershell能轻松应对那肯定就是首选了。










