草庐IT

C#通过HttpListener简单实现http服务器,实现局域网访问

逐浪破风 2024-01-17 原文

以下代码简单实现HTTP,监听端口"http://192.168.0.147:8080/"等即监听本地。可在本地直接访问,然后根据访问传来的端口后面的指令来判断返回值。


```csharp
 class Program 
    {
        //static string url="http://localhost:8080/";
        static string url = "http://*:8080/";
        //static string url = "http://127.0.0.1:8080/";
        static string urlThis = "http://192.168.0.147:8080/";
        //static string urlThis = "http://*:8080/";
        static void Main(string[] args)
        {
            //Console.WriteLine("Hello World!");
            //Program a = new Program();
            //a.Setup(8080);
            //Console.Read();

            sSocket = new HttpListener();
            sSocket.Prefixes.Add(url);
            sSocket.Start();
            sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);
            Console.Read();
        }


        static HttpListener sSocket = null;
        static void GetContextCallBack(IAsyncResult ar)
        {
            try
            {
                sSocket = ar.AsyncState as HttpListener;
                HttpListenerContext context = sSocket.EndGetContext(ar);
                sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);
                HttpListenerResponse response = context.Response;
                Console.WriteLine(context.Request.Url.PathAndQuery);
                //其它处理code
                if (context.Request.Url.PathAndQuery == "/getDateTime")
                {
                    //给客户端返回指定时间
                    string responseString = string.Format("<HTML><BODY> {0}</BODY></HTML>", DateTime.Now);
                    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
                    //对客户端输出相应信息.
                    response.ContentLength64 = buffer.Length;
                    System.IO.Stream output = response.OutputStream;
                    output.Write(buffer, 0, buffer.Length);
                    output.Close();
                }
                //返回文件 文本
                if (context.Request.Url.PathAndQuery == "/getDateTimeText")
                {
                    //给客户端返回指定时间文本
                    System.Threading.ThreadPool.QueueUserWorkItem(LoadFile.Method4, context);
                }
                //返回文件 图片
                if (context.Request.Url.PathAndQuery == "/getBiaoqingPng")
                {
                    //给客户端返回指定图片
                    System.Threading.ThreadPool.QueueUserWorkItem(LoadFile.Method5, context);
                }
                //返回网页 带图片
                if (context.Request.Url.PathAndQuery == "/getHtmlBiaoqingPng")
                {
                    Console.WriteLine("Hello World!");
                    //返回指定的网页带图片
                    string responseString = string.Format("<HTML><img src={0} alt =\"\"></HTML>", urlThis + "getBiaoqingPng");
                    byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
                    //对客户端输出相应信息.
                    response.ContentLength64 = buffer.Length;
                    System.IO.Stream output = response.OutputStream;
                    output.Write(buffer, 0, buffer.Length);
                    output.Close();
                }

            }
            catch { }
        }


        HttpListener httpListener = new HttpListener();
        public void Setup(int port = 8080)
        {            
             httpListener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
             httpListener.Prefixes.Add(string.Format("http://*:{0}/", port));//如果发送到8080 端口没有被处理,则这里全部受理,+是全部接收
             httpListener.Start();//开启服务
             Receive();//异步接收请求
        }

        private void Receive()
        {
            httpListener.BeginGetContext(new AsyncCallback(EndReceive), null);
        }

        private void EndReceive(IAsyncResult ar)
        {
            HttpListenerContext context = httpListener.EndGetContext(ar);
            Dispather(context);//解析请求
            Receive();
            Console.WriteLine(context.Request.Url.PathAndQuery);
        }
 
        RequestHelper RequestHelper;
        ResponseHelper ResponseHelper;
        void Dispather(HttpListenerContext context)
        {
            HttpListenerRequest request = context.Request;
            HttpListenerResponse response = context.Response;
            RequestHelper = new RequestHelper(request);
            ResponseHelper = new ResponseHelper(response);
            RequestHelper.DispatchResources(fs => {
                 ResponseHelper.WriteToClient(fs);// 对相应的请求做出回应
            });
        }
    }

代码写好之后,可以直接VS调试运行,但有些东西需要提前弄好。
防火墙相关,需要运行入网以及一些操作,可以直接选择关闭防火墙,一键最方便。
控制面板上面可以直接关闭防火墙。
然后就是管理员身份运行CMD。
以管理员CMD命令行执行:
①先删除可能存在的错误urlacl,这里的号代指localhost、127.0.0.1、192.168.199.X本地地址和+号等。
命令:netsh http delete urlacl url=http://
:8080/
举例:netsh http delete urlacl url=http://+:8080/

②将上面删除的号地址重新加进url,user选择所有人
命令:netsh http add urlacl url=http://
:8080/ user=Everyone
举例:netsh http add urlacl url=http://+:8080/ user=Everyone

③CMD配置防火墙
netsh advfirewall firewall Add rule name=“命令行Web访问8080” dir=in protocol=tcp localport=8080 action=allow
经过如上设置服务端就可以以httpListener.Prefixes.Add(“http://+:8080/”);监听地址开启监听。
客户端可以通过访问服务端8080端口。服务端本机也可以在浏览器中以localhost和127.0.0.1访问自身http服务器。
主要是netsh http add urlacl url=http://*:8080/ user=Everyone把这个运行之后,则可以在局域网电脑进行访问到自己的http,诸如返回文件,网页等都可以,然后具体的http搭建可以参考以下网址:

https://www.cnblogs.com/zhanhengzong/archive/2012/12/11/2813254.html

里边有很详细的http服务器内容,包括打开网页,下载文件,断点续传等等。
如此,基本上一个http服务器就完成了,可以在window系统的服务器上直接运行打包出来的exe,配置相关的部署,则可以通过公网IP等访问了。

有关C#通过HttpListener简单实现http服务器,实现局域网访问的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  3. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  4. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  5. ruby - 通过 ruby​​ 进程共享变量 - 2

    我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是

  6. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  7. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  8. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  9. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  10. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

随机推荐