2

【Powershell】Powershell实现TCP通讯

 8 months ago
source link: https://blog.51cto.com/mlxia/9196719
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

为什么要在做这个?

PowerShell 进行 TCP 通信可以在许多场景中发挥作用,包括但不限于以下几个方面:

  1. 网络服务监控和管理:通过 PowerShell,你可以编写脚本来检查服务器上的网络服务是否可用,例如检查某个端口是否打开、某个服务是否正在运行等。这对于监控和管理网络服务的健康状态非常有用。
  2. 远程服务器管理:PowerShell 提供了与远程计算机进行通信的功能,包括通过 TCP 连接执行命令和脚本。这使得你可以远程管理服务器、执行远程命令、获取远程计算机的信息等。
  3. 自动化任务和脚本:通过 PowerShell 的 TCP 通信功能,你可以编写脚本来执行各种自动化任务,如与网络设备进行通信、与 Web 服务进行交互、与其他应用程序进行数据交换等。这对于自动化任务和脚本编写非常有帮助。
  4. 网络编程和测试:如果你对网络编程感兴趣,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.TcpClientSystem.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及端口使用情况

【Powershell】Powershell实现TCP通讯_.NET Framework

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

【Powershell】Powershell实现TCP通讯_通讯_02

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

【Powershell】Powershell实现TCP通讯_Powershell_03

证明可以连通

【Powershell】Powershell实现TCP通讯_Powershell_04

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

【Powershell】Powershell实现TCP通讯_通讯_05

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

在服务器端接收Client的数据

【Powershell】Powershell实现TCP通讯_通讯_06

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

【Powershell】Powershell实现TCP通讯_夏明亮_07

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

【Powershell】Powershell实现TCP通讯_夏明亮_08

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

【Powershell】Powershell实现TCP通讯_TCP_09

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

【Powershell】Powershell实现TCP通讯_.NET Framework_10

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

【Powershell】Powershell实现TCP通讯_.NET Framework_11

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

【Powershell】Powershell实现TCP通讯_夏明亮_12

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

【Powershell】Powershell实现TCP通讯_通讯_13

然后在客户端接收数据

【Powershell】Powershell实现TCP通讯_.NET Framework_14

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

【Powershell】Powershell实现TCP通讯_Powershell_15
【Powershell】Powershell实现TCP通讯_.NET Framework_16

补充:客户端和服务器端的发生和接收操作并不是死板的一发一收;而是双方都可以连续多次发送,而接收方则可以在发送方多次发送后一次性地从stream中取出数据。

我为什么些这篇文章呢?因为再最近的项目实施的过程中出现一个问题,服务器的端口明明是开放访问的且没有任何异常;但是同网段的其他服务器就是无法访问这个端口,其他端口有的正常有的不正常;那么肯定是怀疑环境中存在安全软件或装置进行了阻止,但是用户那边坚持说没有阻止访问;那我们就想到把我们的服务器程序先停止释放端口,然后使用powershell侦听这个端口,然后测试该端口是否可以访问;凭此来反证环境中存在未知的安全装置。

为什么不用现成的工具呢?一来好用的工具少,二来生产环境安全要求较高也担心小工具会有安全风险;既然powershell能轻松应对那肯定就是首选了。

如果是linux则更加方便直接使用nc工具就可以了;如果有机会我也会写一些关于nc的用法。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK