PowerShell function that sends a TCP request to a remote computer, and returns the response. If you do not supply input to this script, via either the pipeline or the -InputObject parameter, the script operates in interactive mode.
function Send-TcpRequest
{
##############################################################################
##
## Send-TcpRequest
##
## From Windows PowerShell Cookbook (O'Reilly)
## by Lee Holmes (http://www.leeholmes.com/guide)
##
##############################################################################
<#
.SYNOPSIS
Send a TCP request to a remote computer, and return the response.
If you do not supply input to this script (via either the pipeline, or the
-InputObject parameter,) the script operates in interactive mode.
.EXAMPLE
PS > $http = @"
GET / HTTP/1.1
Host:bing.com
`n`n
"@
$http | Send-TcpRequest bing.com 80
#>
param(
## The computer to connect to
[string] $ComputerName = "localhost",
## A switch to determine if you just want to test the connection
[switch] $Test,
## The port to use
[int] $Port = 80,
## A switch to determine if the connection should be made using SSL
[switch] $UseSSL,
## The input string to send to the remote host
[string] $InputObject,
## The delay, in milliseconds, to wait between commands
[int] $Delay = 100
)
Set-StrictMode -Version 3
[string] $SCRIPT:output = ""
## Store the input into an array that we can scan over. If there was no input,
## then we will be in interactive mode.
$currentInput = $inputObject
if(-not $currentInput)
{
$currentInput = @($input)
}
$scriptedMode = ([bool] $currentInput) -or $test
function Main
{
## Open the socket, and connect to the computer on the specified port
if(-not $scriptedMode)
{
write-host "Connecting to $computerName on port $port"
}
try
{
$socket = New-Object Net.Sockets.TcpClient($computerName, $port)
}
catch
{
if($test) { $false }
else { Write-Error "Could not connect to remote computer: $_" }
return
}
## If we're just testing the connection, we've made the connection
## successfully, so just return $true
if($test) { $true; return }
## If this is interactive mode, supply the prompt
if(-not $scriptedMode)
{
write-host "Connected. Press ^D followed by [ENTER] to exit.`n"
}
$stream = $socket.GetStream()
## If we wanted to use SSL, set up that portion of the connection
if($UseSSL)
{
$sslStream = New-Object System.Net.Security.SslStream $stream,$false
$sslStream.AuthenticateAsClient($computerName)
$stream = $sslStream
}
$writer = new-object System.IO.StreamWriter $stream
while($true)
{
## Receive the output that has buffered so far
$SCRIPT:output += GetOutput
## If we're in scripted mode, send the commands,
## receive the output, and exit.
if($scriptedMode)
{
foreach($line in $currentInput)
{
$writer.WriteLine($line)
$writer.Flush()
Start-Sleep -m $Delay
$SCRIPT:output += GetOutput
}
break
}
## If we're in interactive mode, write the buffered
## output, and respond to input.
else
{
if($output)
{
foreach($line in $output.Split("`n"))
{
write-host $line
}
$SCRIPT:output = ""
}
## Read the user's command, quitting if they hit ^D
$command = read-host
if($command -eq ([char] 4)) { break; }
## Otherwise, Write their command to the remote host
$writer.WriteLine($command)
$writer.Flush()
}
}
## Close the streams
$writer.Close()
$stream.Close()
## If we're in scripted mode, return the output
if($scriptedMode)
{
$output
}
}
## Read output from a remote host
function GetOutput
{
## Create a buffer to receive the response
$buffer = new-object System.Byte[] 1024
$encoding = new-object System.Text.AsciiEncoding
$outputBuffer = ""
$foundMore = $false
## Read all the data available from the stream, writing it to the
## output buffer when done.
do
{
## Allow data to buffer for a bit
start-sleep -m 1000
## Read what data is available
$foundmore = $false
$stream.ReadTimeout = 1000
do
{
try
{
$read = $stream.Read($buffer, 0, 1024)
if($read -gt 0)
{
$foundmore = $true
$outputBuffer += ($encoding.GetString($buffer, 0, $read))
}
} catch { $foundMore = $false; $read = 0 }
} while($read -gt 0)
} while($foundmore)
$outputBuffer
}
. Main
}