基于PowerShell的httpListener多线程Web Server的实现

在PowerShell中,可以通过HttpListener 实现一个简单的Web服务器。但在实践当中,这个服务是串行,每次只能处理一个连接,性能不好,只能做一些简单的用途。如果要同时服务多个连接请求,需要在PowerShell使用多线程来进行处理。下面是具体的实践:

#定义一个哈希表全局变量,用来保存WebServer的全局信息
$PSWeb = [Hashtable]::Synchronized(@{})
#定义用于线程的脚本块,该脚本用于处理具体的服务请求
#传入两个参数,一个是request请求对象,一个是Respone对象
$PSWeb.ScriptBlock = {
    Param([System.Net.HttpListenerRequest]$req,System.Net.HttpListenerResponse]$rsp)

#在代码块里不能使用代码块以外的地方自定义的函数。但是可以在代码块里自定义定义函数哦
#这个函数用于网客户端返回JASON信息
    function Ret_response([System.Net.HttpListenerResponse]$resp,$ret,$msg){
        $retstr = '{"ret":' + $ret + ',"msg":"' + $msg + '"}'
        $retbytes = [System.Text.Encoding]::UTF8.GetBytes($retstr)
        $resp.StatusCode = "200"
        $resp.ContentType = 'application/json'
        $resp.ContentLength64 = $retbytes.Length
    }
#直接调用自定义的函数,向客户端返回信息
    Ret_response $rsp 0 "海内存知己,天涯若比邻"
#关闭连接
    $rsp.Close()
#返回
    return
}

#定义一个运行线程用的Runspace池,这个池可以限制同时运行的处理请求的线程数量,本例设置为5
$PSWeb.RunspacePool = [Runspacefactory]::CreateRunspacePool(1,5)
#设置监听的IP地址和端口号
$url = "http://*:8888/"

Try {
      #建立HttpListener对象,设置服务目录并开始监听
      
       $PSWeb.listener = New-Object System.Net.HttpListener
       $PSWeb.listener.Prefixes.Add($url)
       $PSWeb.listener.Start()
      
    #打开RunSpacePool
       $PSWeb.RunspacePool.Open()
       Write-Host "服务启动: $url..."
        
       #循环处理请求
        while ($PSWeb.listener.IsListening){
             #阻塞读取服务请求
             $content = $PSWeb.listener.GetContext()
             #读到服务请求后,建立相应的线程并异步运行
             $ps = [PowerShell]::Create().AddScript($PSWeb.ScriptBlock)
            #设置线程的Runspacepool
            $ps.RunspacePool = $PSWeb.RunspacePool
            #按顺序传入参数
            [void]$ps.AddArgument($content.Request)
            [void]$ps.AddArgument($content.Response)
            #异步运行线程
            [void]$ps.BeginInvoke()
        }
}
catch
{
          #异常处理
          Write-Error "有错误发生:"
          $_.Exception.Message
}
finally
{
           #释放资源
           $PSWeb.listener.Stop()
           $PSWeb.RunspacePool.Close()
}

具体的服务可以在代码块里实现。
这段代码可以在powershell里实现多线程的Web Server服务,能正常运行。当然还有不小的提升空间,比如说可以在循环里取些线程的返回值,做一些线程的清理操作之类的工作。

#定义一个数组,保存运行中的线程信息
$PSWeb.Jobs = New-Object System.Collections.ArrayList
#然后在循环里改成如下代码:
while ($PSWeb.listener.IsListening){
     $content = $PSWeb.listener.GetContext()
     $ps = [PowerShell]::Create().AddScript($PSWeb.ScriptBlock)
     $ps.RunspacePool = $PSWeb.RunspacePool
     [void]$ps.AddArgument($content.Request)
     [void]$ps.AddArgument($content.Response)
     [void]$ps.BeginInvoke()
     #往Jobs数据里加入新建的线程信息
     [void]$PSWeb.Jobs.Add((New-Object PSObject -Property @{
        Ps = $ps
        Result = $ps.BeginInvoke()
     }))
    #定义一个数组,保存已经完成运行的线程   
     $CompletedJobs = @() 
     
#遍历Jobs数组,查找已完成运行的线程,处理返回结果
      ForEach ( $Job in $PSWeb.Jobs)  {
         if ($Job.Result.IsCompleted)
         {
               #已运行完成的线程,处理器返回结果
                Write-Host $Job.Ps.EndInvoke($Job.Result)
               #释放线程资源
                $Job.Ps.Dispose()  
               #将已完成的线程加入到临时的数组里,以便可以从Jobs数组里删除
                $CompletedJobs += $Job
         }
     }    
    #从Jobs列表中删除已完成运行的线程
     foreach ($Job in $CompletedJobs)  {
          $PSWeb.Jobs.Remove($Job)
     }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值