こんにちは、今回はPowershellでTCPサーバーを作成する手順について記載します。

セキュリティの観点から、自由にアプリケーションをインストールできない企業などが多いのではないでしょうか。

でも、ちょっと疎通確認をしたいといった状況で不便に感じることがあります。

そこで、Windows標準機能であるPowershellを使って簡易的にTCPサーバー機能を実装してみましょう。

Powershellでは.Net Frameworkが使えるので、特別なアプリケーションをインストールしなくても、簡単なTCPサーバーくらいなら作成できてしまいます。

それでは早速作っていきます。

待ち受けIPとポートの設定

まずは、待ち受けるIPアドレスとポートを設定します。

IPアドレスの指定方法には以下のような種類があります。

項目説明
[System.Net.IPAddress]::Any0.0.0.0
IPv4の全インターフェースで待ち受ける。
[System.Net.IPAddress]::Loopback127.0.0.1
ローカルホストでのみ待ち受ける。
外部からの接続は不可。
[System.Net.IPAddress]::Parse(“10.20.30.40”)特定のIPアドレスで待ち受ける。

PowerShell
$bind_ip = [System.Net.IPAddress]::Loopback
$bind_port = 8080

リスナーを作成する

IPアドレスとポートを指定してリスナーを作成します。

リスナーの定義には[System.Net.Sockets.TcpListener]クラスを使用します。
定義したリスナーに対してStart()メソッドを呼び出すことで待ち受けを開始します。

接続を待ち受けるだけの基本構成は以下のようになります。

PowerShell
# リスナー作成と開始
$listener = [System.Net.Sockets.TcpListener]::new($bind_ip, $bind_port)
$listener.Start()

# クライアント接続待ち受け
$client = $listener.AcceptTcpClient()

# 接続後処理
$client.Close()
$listener.Stop()

最終的な形

PowerShell
# TCPサーバースケルトンの作成

# 待ち受けIP
$bind_ip = [System.Net.IPAddress]::Loopback
$bind_port = 8080

# リスナーの作成

$listener = [System.Net.Sockets.TcpListener]::new($bind_ip, $bind_port)
$listener.Start()

Write-Host "Listening on 127.0.0.1 : $bind_port"

# クライアントハンドラ
function Invoke-Client {

    param([System.Net.Sockets.TcpClient] $client)

    try {
        $stream = $client.GetStream()
        # 最大1024バイトを受信
        $buffer = New-Object byte[] 1024
        $count = $stream.Read($buffer, 0, $buffer.Length)

        # 受信バイトの表示
        $requestBytes = $buffer[0..($count-1)]
        Write-Host "Receive: $requestBytes"
        $requestText = [System.Text.Encoding]::ASCII.GetString($requestBytes)
        Write-Host "ReceiveText: $requestText"

        # パケットの返送
        $response = [System.Text.Encoding]::ASCII.GetBytes("ACK")
        $stream.Write($response, 0, $response.Length)
    }
    catch {
        Write-Host "$_"
    }
    finally {
        if ($stream) {$stream.Close()}
        if ($client) {$client.Close()}
    }
}


while ($true) {
    $client = $listener.AcceptTcpClient()
    $remote = $client.Client.RemoteEndPoint.ToString()

    Write-Host "Accepted connection from: $remote"
    Invoke-Client -client $client
}