c# - 生产就绪,多线程 c# http 服务器

标签 c# httplistener

我在 c# .NET 中实现了一个 HTTP 服务器:

public class HttpServer
{
    private HttpListener listener;

    public HttpServer()
    {
        listener = new HttpListener();
        listener.Prefixes.Add("http://localhost:8080/");
    }

    public void Start()
    {
        lock(this) {
            listener.Start();
            AsyncProcessing(listener);
        }
    }

    public void Stop()
    {
        lock (this) {
            listener.Stop();
        }
    }

    private void AsyncProcessing(HttpListener listener)
    {
        if (listener == null)
            return;

        listener.BeginGetContext(new AsyncCallback(Callback), listener);
    }

    private void Callback(IAsyncResult result)
    {
        HttpListenerContext context = null;

        lock(this) {
            HttpListener listener = (HttpListener)result.AsyncState;
            if (!listener.IsListening)
                return;

            context = listener.EndGetContext(result);

            AsyncProcessing(listener);
        }

        /* handle request */
    }
}

我对这个实现有一些疑问:

  • 我在这里和那里添加了一些锁来防止竞争条件,但我很困惑:真的需要那些吗?我在文档中读到所有公共(public)非静态方法都不是线程安全的。为什么我没有看到考虑到这一事实的代码?
  • HttpListenerContext 的行为如何?他与 HttpListener 有某种联系吗?或者我可以同时使用多个 HttpListenerContext 吗?
  • 我听说 HttpListener 不能用于生产系统,但我从未见过支持这种说法的论据。是真是假?
  • 是否还有其他我应该考虑但未提及的事项?

谢谢你的想法

最佳答案

请记住,我不是多线程方面的专家,因此您应该尽可能地注意验证我所说的任何内容。

如果其他人知道,并且想窃取我的全部答案并编辑或更正细节,请随意这样做。

让我们一一解答您的问题:

I added some locks here and there to prevent race conditions, but I'm confused: Are those really needed? I read in the documentation that all public non-static methods are NOT thread safe. Why haven't I seen code where this fact is considered?

好吧,是的,不是。锁通常用于防止多个线程同时访问同一数据结构,因为它会破坏数据结构。考虑在一个线程上对数组进行排序,并在另一个线程的中间插入一个元素,正确地为这两个线程计时会破坏数组的内容。

现在,在您的代码中,您锁定了 this,这绝不是一个好主意。外部代码可能也锁定了同一个对象,这是你无法控制的,所以为了创建生产就绪代码,我不会那样做。

如果您的代码需要锁,我会构造特定的锁对象并使用它们。

换句话说,添加:

private readonly object _Lock = new object();

然后在所有有 lock(this) 的地方将其替换为 lock(_Lock)。这样,如果需要,您还可以拥有多个锁。

至于是否真的需要锁,我不是 100% 确定。我不确定的是您在调用 Stop 之前锁定,并且在回调中锁定并在锁定内检查监听器是否仍在运行。

这将防止您在接受请求后但在实际处理请求之前停止监听器。换句话说,听起来您会在打开请求仍在处理的情况下阻止关闭服务器。

但是,不,你不会阻止它,因为你可能会在回调中离开锁定部分后停止服务器,但在注释代码完全执行期间或之前,所以你仍然会遇到这个问题。

但是 这也意味着您已经有效地序列化了一些回调方法,即您调用 EndGetContext 并重新启动 BeginGetContext 循环的部分。我不知道这是否是一个好的模式。

How does the HttpListenerContext behave? Does he have some sort of connection to the HttpListener? Or can I use multiple HttpListenerContexts concurrently?

这里我来猜一猜。该类没有对监听器类的引用,,它有一种线程安全的方式与之合作。

如果对请求/响应数据的每次访问都必须序列化,那么它就不是一个基于线程的 http 监听器系统。

无论如何,如果有疑问,请检查您正在访问的上下文类的方法和/或属性的文档,如果您需要采取措施确保线程安全,文档会这样说。

I heard HttpListener wouldn't be ready for production systems, but I've never seen an argument supporting this claim. Is it true or not?

(见问题评论)

Are there other things I should consider which I haven't mentioned?

多线程代码难以编写。从你的问题来看,我会大胆猜测你没有做很多,老实说,虽然我做了很多,但我仍然觉得我如履薄冰。

因此,我的建议如下:

  • 真的需要多线程吗?
  • 您是否有其他对此了解更多的同事可以帮助您?

关于c# - 生产就绪,多线程 c# http 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6371741/

相关文章:

C# HttpListener 在 SSL 上完全失败

java - Glassfish 3.1.2 build 5 WAR 部署问题

vb.net - 在 .NET 中解码基本授权的最简单方法

c# - 将查询理解转换为 LINQ 中的可枚举扩展方法

C# 用韩文编码保存文件

c# - Kendo.Mvc.dll 的 NuGet

.net - HTTPListener与 native HTTP性能

c# - 通过查看其二进制内容以编程方式找出文件类型。可能的?

c# - 如何确定 WCF 3 和 ASP.NET 是否以编程方式注册到 IIS 7

.net - 是否可以将 HTTP2 与 HTTPListener 一起使用