.net 如何使用powershell连接tcp socket发送和接收数据?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29759854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 09:39:27  来源:igfitidea点击:

How to connect to tcp socket with powershell to send and receive data?

.netsocketspowershelltcp

提问by gazsiazasz

I have written a little Powershell script.

我写了一个小的 Powershell 脚本。

It uses .Net System.IO.StreamReader and System.IO.StreamWriter to read and write data from/to the TCP socket.

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

I would like to connect to a socket telnet style with it and send/receive commands.

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

I am trying to read the lines with the ReadLine() method from the System.IO.StreamReader but the data from the server maybe does not arrive in time(?) or IDK. I am not using async commands. Please help me with that!

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

Here is my script:

这是我的脚本:

$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()

And here is the output:

这是输出:

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>

回答by Jan Chrbolka

Try using a buffer to read in response. The code would look like this:

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

$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()

回答by Chris Horan

I found that the NetworkStream DataAvailable property wasn't enough on its own, and that it needed a little nudge before entering the second while loop. I've tested this and it works like a charm when connected to a CISCO device over telnet.

我发现 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()

回答by gazsiazasz

I have tried all the solutions.. Chris's suggestion helped, it is needed to check if there's something coming from the reader also. Now it is working fine.

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

$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()

And here is the output:

这是输出:

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>

回答by Evgeny Danilenko

The reason why your read line hangs is probably because you are not terminating the string that you send with '\n'.

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

Client code:

客户端代码:

[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
    }
}

Server code (nodejs)

服务器代码(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");

it just werks.

它只是起作用。