Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
685 views
in Technique[技术] by (71.8m points)

c# - Is there a way to enable the SO_REUSEADDR socket option when using System.Net.HttpListener?

Been searching for this for over an hour now, and I have not found in documentation nor in examples on the web how to enable the SO_REUSEADDR option when working with the HttpListener class.

My specific use case is within a Powershell script, but even if there is an answer in C#, that would be fine. This is about as cut-and-dry as it gets:

$Listener = New-Object System.Net.HttpListener
$Listener.Prefixes.Add('http://+:9999/')
Try
{
    $Listener.Start()
    # While loop here to handle requests; omitted for brevity
}
Catch
{
    # omitted here for brevity
}

There are times where I Ctrl-C to break out of the script while testing, and leaving the loop this way does not allow $Listener.Stop() to be called and the socket properly closed. (Yes, I know - don't do this if it breaks things)

Normally, when I need a listening socket, I make use of SO_REUSEADDR to handle those times where things don't clean up properly to allow me to restart my listener without having to wait 30 minutes for the port to be available again. Is there a way to do this with HttpListener and I'm just missing it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

No, you can't use SO_REUSEADDR with HttpListener.

The reason is that the HttpListener doesn't actually manage the underlying socket - it simply registers application-level prefixes with the HTTP.sys driver, who in turn manages the underlying connection.

To use SO_REUSEADDR, you could create a TcpListener and set the socket option on the underlying socket (accessible through the Server property) with SetSocketOption():

$TcpListener = New-Object System.Net.Sockets.TcpListener 9999
$TcpListener.Server.SetSocketOption("Socket", "ReuseAddress", 1)
$TcpListener.Start()

But now you have to implement all the convenient things that HttpListener provides on you own (header parsing, content validation etc.).


That being said, this may solve the practical issue you face:

try{
    $Listener.Start()
}
catch{
}
finally{
    $Listener.Stop()
    $Listener.Dispose()
}

(don't paste this into you prompt/ISE, you need to save this to a script, or enclose in a script block for finally to be evaluated properly on interruption)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...