A simple in-process HTTP server for UWP

原文 http://www.dzhang.com/blog/2012/09/18/a-simple-in-process-http-server-for-windows-8-metro-apps

简单来说,就是在UWP中做一个支持GET请求简单的Web Server,本实例UWP(server) 与 Winform(client) 在同一机子将无法通讯,但UWP(server)写client代码可调用调试。

注意,Package.appxmanifest 选项“功能”卡中的Internet配置。

Below is some code for a simple HTTP server for Metro/Modern-style Windows 8 apps. This code supports GET requests for a resource located at the root-level (e.g. http://localhost:8000/foo.txt) and looks for the corresponding file in the Data directory of the app package. This might be useful for unit testing, among other things.

public class HttpServer : IDisposable {
  private const uint BufferSize = 8192;
  private static readonly StorageFolder LocalFolder
               = Windows.ApplicationModel.Package.Current.InstalledLocation;

  private readonly StreamSocketListener listener;

  public HttpServer(int port) {
    this.listener = new StreamSocketListener();
    this.listener.ConnectionReceived += (s, e) => ProcessRequestAsync(e.Socket);
    this.listener.BindServiceNameAsync(port.ToString());
  }

  public void Dispose() {
    this.listener.Dispose();
  }

  private async void ProcessRequestAsync(StreamSocket socket) {
    // this works for text only
    StringBuilder request = new StringBuilder();
    using(IInputStream input = socket.InputStream) {
      byte[] data = new byte[BufferSize];
      IBuffer buffer = data.AsBuffer();
      uint dataRead = BufferSize;
      while (dataRead == BufferSize) {
        await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
        request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
        dataRead = buffer.Length;
      }
    }

    using (IOutputStream output = socket.OutputStream) {
      string requestMethod = request.ToString().Split('\n')[0];
      string[] requestParts = requestMethod.Split(' ');

      if (requestParts[0] == "GET")
        await WriteResponseAsync(requestParts[1], output);
      else
        throw new InvalidDataException("HTTP method not supported: "
                                       + requestParts[0]);
    }
  }

  private async Task WriteResponseAsync(string path, IOutputStream os) {
    using (Stream resp = os.AsStreamForWrite()) {
      bool exists = true;
      try {
        // Look in the Data subdirectory of the app package
        string filePath = "Data" + path.Replace('/', '\\');
        using (Stream fs = await LocalFolder.OpenStreamForReadAsync(filePath)) {
          string header = String.Format("HTTP/1.1 200 OK\r\n" +
                          "Content-Length: {0}\r\n" +
                          "Connection: close\r\n\r\n",
                          fs.Length);
          byte[] headerArray = Encoding.UTF8.GetBytes(header);
          await resp.WriteAsync(headerArray, 0, headerArray.Length);
          await fs.CopyToAsync(resp);
        }
      }
      catch (FileNotFoundException) {
        exists = false;
      }

      if (!exists) {
        byte[] headerArray = Encoding.UTF8.GetBytes(
                              "HTTP/1.1 404 Not Found\r\n" +
                              "Content-Length:0\r\n" +
                              "Connection: close\r\n\r\n");
        await resp.WriteAsync(headerArray, 0, headerArray.Length);
      }

      await resp.FlushAsync();
    }
  }
}

Usage:

const int port = 8000;
using (HttpServer server = new HttpServer(port)) {
  using (HttpClient client = new HttpClient()) {
    try {
      byte[] data = await client.GetByteArrayAsync(
                    "http://localhost:" + port + "/foo.txt");
      // do something with
    }
    catch (HttpRequestException) {
      // possibly a 404
    }
  }
}

 

Notes:

  • The app manifest needs to declare the "Internet (Client & Server)" and/or the "Private Networks (Client & Server)" capability.
  • Due to the Windows 8 security model:
    • A Metro app can access network servers within its own process.
    • A Metro app Foo can access network servers hosted by another Metro app Bar iff Foo has a loopback exemption. You can use CheckNetIsolation.exe to do this. This is useful for debugging only, as it must be done manually.
    • A Desktop app cannot access network servers hosted by a Metro app. The BackgroundDownloader appears to fall into this category even though that is an API available to Metro apps.
时间: 2024-11-05 04:55:55

A simple in-process HTTP server for UWP的相关文章

A simple IOCP Server/Client Class

  Download demo project v1.13 - 64.4 Kb Download source v1.13 - 121 Kb 1.1 Requirements This article expects the reader to be familiar with C++, TCP/IP, socket programming, MFC, and multithreading. The source code uses Winsock 2.0 and IOCP technology

基于Service Broker的异步消息传递

这里演示同一个SQL Server中不同数据库之间的基于Service Broker的异步消息传递,其中Stored Procedure充当Service Program.HelloWorldDB为目标数据库,DotNetFun2则为消息发送发的数据库. 同时,假设Server Broker的基本对象类型已经创建,如MessageType(XMLMessage), Contract(XMLContract), Queue(SendingQueue and ReceivingQueue)等等,具体

【OH】Glossary Oracle词汇表(下)

[OH]Glossary Oracle词汇表(下) Oracle? Database Installation Guide 11g Release 2 (11.2) for Linux E47689-05 Glossary ● Oracle Automatic Storage Management disk group A set of disk devices that Oracle Automatic Storage Management (Oracle ASM) manages as a

A Unix Utility You Should Know About: Netcat

This is the second post in the article series about Unix utilities that you should know about. In this post I will introduce you to the netcat tool or simply nc. Netcat is often referred to as a "Swiss Army knife" utility, and for a good reason.

Http Status Codes

原文:http://httpstatus.es/ 1xx informational 100 client should continue with request 101 server is switching protocols 102 server has received and is processing the request 103 resume aborted PUT or POST requests 122 URI is longer than a maximum of 208

How to Quickly Implement Nginx-based Website Monitoring

Introduction: In this article, we dive into a scenario that discusses a rapidly growing business with an application that provides users with e-commerce data statistics web services. The application adopts the common distributed Nginx + app architect

工作流引擎Activiti 专题

https://github.com/Activiti/Activiti Quick Start Guide This quick start assumes: Familiarity with Maven and Java A development environment with Java The following variables will be referenced in this tutorial Variable Description $mvnProject The root

PostgreSQL pg_hba.conf "search bind" configure Use LDAP auth

上一篇BLOG讲了一下在PostgreSQL的pg_hba.conf中配置ldap simple bind的认证方式. PostgreSQL还支持另一种bind方式. search+bind 相当于PostgreSQL server需要两次和ldap server交互. 交互过程如下. In the second mode, which we will call the search+bind mode, the server first binds to the LDAP directory

OGRE Code Review HOWTO

Table of Contents Introduction The Process What to Look For Style Design Guidelines OGRE Specific Guidelines Introduction The time has come for all good men to come to the aid of their favorite rendering engine. The OGRE Project needs you to help wit