`

用edas写一个简单的http Server,扩展http协议的处理器

阅读更多

为了说明一下基础tcp开发库是如何扩展来处理上层协议的,我这里用一个简单到极点的Http Server来作为例子。这个例子会处理发到特定端口的所有http请求,并返回显示Hello world的网页。

由于是一个很简单的例子,所以我们并不需要解析完整的Http协议,当然我们是能够很快构建一个http处理器,毕竟这是一个基于文本行的协议,不过即使这样还是需要很大的篇幅,所以我们只需要处理其中一小部份。

首先我们来看看Http的request。http的请求是一串文本,由多个行组成,每行都是key value形式的,第一行表示了请求的方法和路径,由空格隔开,后面的是请求的头,由冒号隔开,不过其中的内容表示什么意思对我们来说没什么意义,我们在这里也不打算处理,我们把它们存在一个hash表里,等待更高级的处理器来处理。

所以首先我们先建立一个类,实现IProcessor接口:

    class HttpProcessor : IProcessor
    {
        #region IProcessor 鎴愬憳

        public void Init(IWorkingSocket Sock)
        {
            throw new NotImplementedException();
        }

        public void NextProcessor(IProcessor NextProcessor)
        {
            throw new NotImplementedException();
        }

        public void PushData(byte[] Data, int ReadCount)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region IDisposable 鎴愬憳

        public void Dispose()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com -->

 

根据前面的分析我们需要在其中用一个HashTable来存储http的请求头信息。

在每一次得到一行数据的时候就分析,是头一行还是header的行。然后将其插入hashtable,如果得到的是一个空行,那么就表明请求结束了,那么我们就将一段html发送回去。

    class HttpProcessor : IProcessor
    {
        private Dictionary<string, string> httpHeader;

        public HttpProcessor()
        {
            httpHeader = new Dictionary<string, string>();
        }

        public event Action<IWorkingSocket,Dictionary<string, string>> OnRequest;

        #region IProcessor 成员

        private IWorkingSocket Conn;

        public void Init(IWorkingSocket Sock)
        {
            Conn = Sock;
        }

        public void NextProcessor(IProcessor NextProcessor)
        {
            //如果没有下级处理器就留空
        }

        public void PushData(byte[] Data, int ReadCount)
        {
            string line = Encoding.ASCII.GetString(Data, 0, ReadCount);
            if (line.Equals("\r\n"))
            {
                if (OnRequest != null)
                {
                    OnRequest(Conn, httpHeader);
                }
            }
            string[] temp = null;   
            if (line.Split(':').Length>1)
            {
                temp = line.Split(':');
                httpHeader.Add(temp[0], temp[1]);
                return;
            }
            if (line.Split(' ').Length > 1)
            {
                temp = line.Split(' ');
                httpHeader.Add(temp[0], temp[1]);
                return;
            }
        }

        #endregion

        #region IDisposable 回收资源

        public void Dispose()
        {
            httpHeader.Clear();
            Conn = null;
        }
        #endregion
    }
<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com -->

 

ok,这样子后我们在处理OnRequest事件的时候就能够接收到一个Dictionary对象,里面就是所有http的头信息,如果我们不关系其中的内容就可以直接在这个事件里返回数据了。

最后的结果:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using org.Alexander.EDAS;

namespace EdasServer
{
    class Program
    {
        static void Main(string[] args)
        {
            Acceptor acp = new Acceptor(8888);
            acp.OnError = (ex, str) =>
            {
                //TO DO:To handle listenner's error
            };
            acp.Accepted = (sock,id,buffersize) =>
            {
                AsyncSocket sk = new AsyncSocket(sock, buffersize);
                sk.ID = id;
                sk.OnError += new Action<Exception, string>(sk_OnError);
                sk.Disconnected += new Action<long>(sk_Disconnected);
                TokenProcessor Proc = new TokenProcessor(0x0A);
                sk.Processor = Proc;
                HttpProcessor httpProc = new HttpProcessor();
                httpProc.OnRequest += new Action<IWorkingSocket, Dictionary<string, string>>(httpProc_OnRequest);
                Proc.NextProcessor(httpProc);
                sk.WaitReceive();
            };
            acp.WaitAsyncAccept();
            Console.ReadKey();
        }

        static void httpProc_OnRequest(IWorkingSocket arg1, Dictionary<string, string> arg2)
        {
            StringBuilder html=new StringBuilder();
            html.Append("<HTML><HEAD><TITLE>test</TITLE></HEAD><BODY><H3>Hello world</H3></BODY></HTML>");
            StringBuilder str = new StringBuilder();
            str.Append("HTTP /1.1 200 OK\r\n");
            str.Append("Date:" + DateTime.Now.ToLongDateString()+"\r\n");
            str.Append("Server: Edas Server(win32)\r\n");
            str.Append("Content-Length: " + html.Length+"\r\n");
            str.Append("Content-Type: text/html\r\n");
            string Data = str.ToString() + "\r\n" + html.ToString();
            arg1.SendToQueue(Encoding.ASCII.GetBytes(Data));
            arg1.Disconnect();
        }
        static void sk_Disconnected(long obj)
        {
            //TO DO:To handle disconnect event
        }
        static void Proc_OnLine(IWorkingSocket arg1, byte[] arg2)
        {
            arg1.SendToQueue(arg2);
        }
        static void sk_OnError(Exception arg1, string arg2)
        {
            //TO DO:Process errors
        }
    }

    class HttpProcessor : IProcessor
    {
        private Dictionary<string, string> httpHeader;

        public HttpProcessor()
        {
            httpHeader = new Dictionary<string, string>();
        }

        public event Action<IWorkingSocket,Dictionary<string, string>> OnRequest;

        #region IProcessor 鎴愬憳

        private IWorkingSocket Conn;

        public void Init(IWorkingSocket Sock)
        {
            Conn = Sock;
        }

        public void NextProcessor(IProcessor NextProcessor)
        {
            //濡傛灉鏆傛椂娌℃湁涓嬬骇澶勭悊鍣ㄧ殑鏃跺€欑暀绌?
        }

        public void PushData(byte[] Data, int ReadCount)
        {
            string line = Encoding.ASCII.GetString(Data, 0, ReadCount);
            if (line.Equals("\r\n"))
            {
                if (OnRequest != null)
                {
                    OnRequest(Conn, httpHeader);
                }
            }
            string[] temp = null;   
            if (line.Split(':').Length>1)
            {
                temp = line.Split(':');
                httpHeader.Add(temp[0], temp[1]);
                return;
            }
            if (line.Split(' ').Length > 1)
            {
                temp = line.Split(' ');
                httpHeader.Add(temp[0], temp[1]);
                return;
            }
        }

        #endregion

        #region IDisposable 鎴愬憳

        public void Dispose()
        {
            httpHeader.Clear();
            Conn = null;
        }
        #endregion
    }
}
<!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin. http://dunnhq.com -->

运行后,打开IE,输入 http://localhost:8888,得到结果如下:

image

分享到:
评论

相关推荐

    edas-config-center

    企业级分布式应用服务EDAS是阿里巴巴提供的一款强大的中间件Platform-as-a-Service(PaaS)产品。它旨在帮助开发者更高效地部署、运行和管理分布式应用程序,特别是基于微服务架构的应用。EDAS的核心功能包括应用...

    EDAS详细的搭建配置开发文档

    同时,还需要下载Pandora容器,这是一个专门用于EDAS的容器扩展,需要解压到Ali-Tomcat的deploy目录下。完成上述步骤后,开发者能够通过查看Pandora容器的目录结构来验证安装是否正确。 在开发工具方面,文档中提到...

    EDAS开发者指南.pdf

    - **3.3.1 RPC**: 远程过程调用机制,允许程序调用另一个地址空间上的程序。 - **3.3.2 ConfigServer (地址注册中心)**: 用于存储服务提供者和服务消费者的地址信息。 - **3.3.3 Diamond (配置中心)**: 用于集中管理...

    阿里云分布式应用服务EDAS-快速入门-D.docx

    阿里云企业级分布式应用服务(Enterprise Distributed Application Service, 简称 EDAS)是一个全面的PaaS平台,它为企业提供了从应用开发、部署、监控到运维的一站式解决方案。本快速入门将指导用户如何开始使用...

    鹰眼跟踪、EDAS燎原, 看高性能服务框架EDAS的架构实践

    《鹰眼跟踪、EDAS燎原,看高性能服务框架EDAS的架构实践》这篇文档主要聚焦于阿里云的EDAS(Enterprise Distributed Application Service)服务框架,这是一个强大的分布式应用管理平台,旨在提供高效率、高性能的...

    EDAS-HSF-BOOT

    在"EDAS-HSF-BOOT"项目中,我们可以看到"pandora-hsf-boot-demo"这个文件,这通常是一个示例项目,用于展示如何使用HSF-BOOT来创建和消费HSF服务。Pandora是阿里巴巴开源的分布式系统治理平台,它集成了HSF,可以...

    阿里edas开发工具包edas-sdk

    阿里edas开发工具包,

    Springboot+HSF分布式服务框架+EDAS注册中心,实现发布订阅模式

    3. **服务消费者**:服务消费者同样是一个Spring Boot应用,通过HSF客户端组件与EDAS注册中心交互,获取服务提供者的列表。HSF客户端会根据预设的策略(如轮询、随机等)选择一个服务实例进行调用。 4. **发布订阅...

    阿里云 专有云Enterprise版 企业级分布式应用服务EDAS V3.1.0 API参考 20171129.pdf

    EDAS提供了一个完整的分布式应用程序解决方案,包括应用程序开发、测试、部署、运维等各个方面。 EDAS API是EDAS的核心组件之一,提供了一组丰富的API接口,允许用户通过API调用来访问EDAS的各种功能。通过EDAS API...

    edas-lite-configcenter.zip

    轻量配置中心edas-lite-configcenter端口修改,默认8080、9600,因为有些安全限制敏感端口,改为18080,19600

    阿里云分布式应用服务EDAS-产品简介-D.docx

    阿里云的分布式应用服务EDAS(Enterprise Distributed Application Service)是一个基于云计算的企业级解决方案,它集成了阿里巴巴中间件团队的成熟分布式技术,旨在为企业提供高效、可扩展且稳定的分布式应用托管...

    EDAS开发培训(初级)v1.0.5.pptx

    【EDAS开发培训(初级)v1.0.5.pptx】是一份关于阿里云的EDAS(Enterprise Distributed Application Service)开发的初级培训材料。EDAS是阿里巴巴为企业级云计算市场提供的高可用分布式解决方案,它基于阿里巴巴...

    edas-config-center.zip_Center_EDAS注册中心_configcenter_edas config

    当一个服务实例启动后,它会向配置中心注册自身的信息,包括服务名、IP、端口等,其他服务可以通过配置中心找到并调用这些服务。 3. **实时推送**:一旦配置发生改变,配置中心会立即推送给所有订阅了该配置的服务...

    阿里云 专有云Enterprise版 企业级分布式应用服务EDAS V3.1.0 产品简介 20171129.pdf

    1. 企业级分布式应用服务EDAS产品简介:EDAS是一款企业级分布式应用服务,旨在帮助用户构建高可用、可扩展、安全的分布式应用系统。 2. 产品版本和文档版本:当前文档版本为V3.1.0,文档版本为20171129。 3. 法律...

    阿里云分布式应用服务EDAS-开发指南.pdf

    2. 使用自己启动的EDAS配置中心,开发者可以快速启动一个EDAS配置中心,将jmenv.tbsite.net指向启动了EDAS配置中心的机器IP,连接自己启动好的配置服务。 在选择使用EDAS配置中心时,需要考虑以下几点: * 在开发...

    通用地震数据采集器EDAS-24GN中CPU数据收发方式.pdf

    通过精心设置SSC工作模式和选择合适的外部时钟输入,再配合使用简单的CPLD进行波形编码和解码,可以构建出一种高效且稳定的专用数据采集系统。这种系统不仅能够应对大数据量的挑战,而且在提高数据处理效率、保证...

    阿里云 专有云Enterprise版 企业级分布式应用服务EDAS V3.3.0 产品简介 20180312.pdf

    EDAS是一个企业级分布式应用服务,提供了企业级的分布式应用解决方案,帮助企业快速构建和部署分布式应用程序。该产品具有高可扩展性、可靠性和高性能等特点。 功能特性部分详细介绍了EDAS的各种功能特性,包括应用...

    EDAS-24-SMS3.EXE

    地震波分析处理软件EDAS-24-SMS3.EXE

Global site tag (gtag.js) - Google Analytics