【问题标题】:How to connect to tcp socket with powershell to send and receive data?如何用powershell连接tcp socket来发送和接收数据?
【发布时间】:2015-06-27 21:14:23
【问题描述】:

我写了一个小小的 Powershell 脚本。

它使用 .Net System.IO.StreamReader 和 System.IO.StreamWriter 从/向 TCP 套接字读取和写入数据。

我想用它连接到套接字 telnet 样式并发送/接收命令。

我正在尝试使用 System.IO.StreamReader 中的 ReadLine() 方法读取行,但来自服务器的数据可能没有及时到达(?)或 IDK。我没有使用异步命令。请帮帮我!

这是我的脚本:

$FTPServer = "localhost"
$FTPPort = "21"

$tcpConnection = New-Object System.Net.Sockets.TcpClient($FTPServer, $FTPPort)
$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true

while ($tcpConnection.Connected)
{
    while ($tcpStream.DataAvailable)
    {
        $reader.ReadLine()
    }

    if ($tcpConnection.Connected)
    {
        Write-Host -NoNewline "prompt> "
        $command = Read-Host

        if ($command -eq "escape")
        {
            break
        }

        $writer.WriteLine($command) | Out-Null
    }
}

$reader.Close()
$writer.Close()
$tcpConnection.Close()

这是输出:

PS C:\Windows\System32\WindowsPowerShell\v1.0> test.ps1
220 Microsoft FTP Service
prompt> user username
331 Password required
prompt> pass password
230-Directory has 58,145,996,800 bytes of disk space available.
prompt> 
230 User logged in.
500 Command not understood.
prompt> help
214-The following commands are recognized (* ==>'s unimplemented).
    ABOR 
    ACCT 
    ADAT *
    ALLO 
    APPE 
    AUTH 
    CCC 
    CDUP 
    CWD 
    DELE 
    ENC *
    EPRT 
    EPSV 
    FEAT 
    HELP 
    HOST 
    LANG 
    LIST 
    MDTM 
    MIC *
    MKD 
    MODE 
    NLST 
    NOOP 
    OPTS 
    PASS 
    PASV 
    PBSZ 
    PORT 
    PROT 
    PWD 
    QUIT 
    REIN 
    REST 
    RETR 
    RMD 
    RNFR 
    RNTO 
    SITE 
prompt> escape

PS C:\Windows\System32\WindowsPowerShell\v1.0>

【问题讨论】:

  • 有一个例子here。它使用缓冲区实现 IO。我认为在您的代码中,您在等待用户输入时错过了 TCP 输入。这个one 也是使用缓冲区实现的。

标签: .net sockets powershell tcp


【解决方案1】:

尝试使用缓冲区读取响应。代码如下所示:

$tcpConnection = New-Object System.Net.Sockets.TcpClient($FTPServer, $FTPPort)
$tcpStream = $tcpConnection.GetStream()
$reader = New-Object System.IO.StreamReader($tcpStream)
$writer = New-Object System.IO.StreamWriter($tcpStream)
$writer.AutoFlush = $true

$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding 

while ($tcpConnection.Connected)
{
    while ($tcpStream.DataAvailable)
    {

        $rawresponse = $reader.Read($buffer, 0, 1024)
        $response = $encoding.GetString($buffer, 0, $rawresponse)   
    }

    if ($tcpConnection.Connected)
    {
        Write-Host -NoNewline "prompt> "
        $command = Read-Host

        if ($command -eq "escape")
        {
            break
        }

        $writer.WriteLine($command) | Out-Null
    }
    start-sleep -Milliseconds 500
}

$reader.Close()
$writer.Close()
$tcpConnection.Close()

【讨论】:

    【解决方案2】:

    我发现仅靠 NetworkStream DataAvailable 属性是不够的,在进入第二个 while 循环之前需要稍微推动一下。我已经对此进行了测试,当通过 telnet 连接到 CISCO 设备时,它就像一个魅力。

    $routerAddress = "192.168.10.126"
    $port = "23"
    $tcp = New-Object System.Net.Sockets.TcpClient($routerAddress,$Port)
    $tcpstream = $tcp.GetStream()
    $reader = New-Object System.IO.StreamReader($tcpStream)
    $writer = New-Object System.IO.StreamWriter($tcpStream)
    $writer.AutoFlush = $true
    
    while ($tcp.Connected)
    {       
    write-host ([char]$reader.Read()) -NoNewline
    while(($reader.Peek() -ne -1) -or ($tcp.Available)){        
        write-host ([char]$reader.Read()) -NoNewline
    }
    if ($tcp.Connected)
    {
        Write-Host -NoNewline "_"
        $command = Read-Host
    
        if ($command -eq "escape")
        {
            break
        }
        $writer.WriteLine($command) | Out-Null
    }     
    }
    $reader.Close()
    $writer.Close()
    $tcp.Close()
    

    【讨论】:

      【解决方案3】:

      我已经尝试了所有解决方案。克里斯的建议有帮助,需要检查是否还有来自读者的东西。现在它工作正常。

      $FTPServer = "localhost"
      $FTPPort = "21"
      
      $tcpConnection = New-Object System.Net.Sockets.TcpClient($FTPServer, $FTPPort)
      $tcpStream = $tcpConnection.GetStream()
      $reader = New-Object System.IO.StreamReader($tcpStream)
      $writer = New-Object System.IO.StreamWriter($tcpStream)
      $writer.AutoFlush = $true
      
      while ($tcpConnection.Connected) {
          while ($tcpStream.DataAvailable -or $reader.Peek() -ne -1 ) {
              $reader.ReadLine()
          }
      
          if ($tcpConnection.Connected) {
              Write-Host -NoNewline "prompt> "
              $command = Read-Host
      
              if ($command -eq "escape") {
                  break
              }
      
              $writer.WriteLine($command) | Out-Null
              Start-Sleep -Milliseconds 10
          }
      }
      
      $reader.Close()
      $writer.Close()
      $tcpConnection.Close()
      

      这是输出:

      220 Microsoft FTP Service
      prompt> user username
      331 Password required
      prompt> pass password
      230 User logged in.
      prompt> help
      214-The following commands are recognized (* ==>'s unimplemented).
          ABOR 
          ACCT 
          ADAT *
          ALLO 
          APPE 
          AUTH 
          CCC 
          CDUP 
          CWD 
          DELE 
          ENC *
          EPRT 
          EPSV 
          FEAT 
          HELP 
          HOST 
          LANG 
          LIST 
          MDTM 
          MIC *
          MKD 
          MODE 
          NLST 
          NOOP 
          OPTS 
          PASS 
          PASV 
          PBSZ 
          PORT 
          PROT 
          PWD 
          QUIT 
          REIN 
          REST 
          RETR 
          RMD 
          RNFR 
          RNTO 
          SITE 
          SIZE 
          SMNT 
          STAT 
          STOR 
          STOU 
          STRU 
          SYST 
          TYPE 
          USER 
          XCUP 
          XCWD 
          XMKD 
          XPWD 
          XRMD 
      214 HELP command successful.
      prompt> list
      150 Opening ASCII mode data connection.
      425 Cannot open data connection.
      prompt> escape
      
      PS C:\Users\gazsiazasz>
      

      【讨论】:

        【解决方案4】:

        您的读取行挂起的原因可能是因为您没有终止使用 '\n' 发送的字符串。

        客户端代码:

        [System.Net.Sockets.TcpClient] $tcpClient = [System.Net.Sockets.TcpClient]::new("localhost", "50001")
        
        $tcpStream = $tcpClient.GetStream()
        [System.IO.StreamReader] $reader = [System.IO.StreamReader]::new($tcpStream)
        [System.IO.StreamWriter] $writer = [System.IO.StreamWriter]::new($tcpStream)
        
        while ($tcpClient.Connected) {
            while ($tcpStream.DataAvailable) {
                $res = $reader.ReadLine()
                Write-Host $res
            }
        }
        

        服务器代码(nodejs)

        const server = net.createServer(socket => {
            socket.write(
                "Testing !" +
                    socket.remoteAddress +
                    ":" +
                    socket.remotePort +
                    "\n"
            );
            socket.pipe(socket);
            console.log("Client connected!");
        });
        server.listen(50001, "localhost");
        

        它只是工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-13
          • 2023-04-11
          • 2020-06-23
          • 2013-07-19
          相关资源
          最近更新 更多