facebook  linkedin  Twitter  skype  Rss googlePlus

Using Http.Sys to receive messages with WSE 2.0

Dec 22 2004
2061

I have completed some of my previous samples by adding Http support without using IIS!!
I have used Http.sys instead, that is the kernel mode Http listener introduced with IIS 6.0. Previously it was only included in Windows 2003 Server, but now is also shipped in Windows XP SP2. 
And more great news, ... .Net Framework 2.0, includes a set of classes to interact with the Http Api's. Then, it is possible to build a lightweight Http receiver without IIS, by using only .Net assemblies. Http.sys is accessible through a .Net class called HttpListener that lives Under the System.Net namespace. I have updated my chat application (that sends point-to-point one-way Soap messages and was developed with 2.0 SP2 and Visual C# 2005 Express) in order to add an Http port to receive incoming messages.
Next, you can find the code for the new HttpPort class:

    
public class HttpPort : IDisposable
    {
        HttpListener m_listener;  //HttpListener is a sealed class, why?
        SoapReceiver m_service;
        Thread loopThread;
 
        public HttpPort(SoapReceiver receiver)
        {
            m_listener = new HttpListener();
            m_listener.Prefixes.Add(Settings.LocalHttpUri.AbsoluteUri);
            m_service = receiver;
        }
 
        public bool Start()
        {
            m_listener.Start();
 
            loopThread = new Thread(mainLoop); //.Net 2.0 feature, note that ThreadStart is not used.
            loopThread.Start();
 
            return m_listener.IsListening;
        }
 
        public bool Stop()
        {
            if(m_listener.IsListening)
                m_listener.Stop();
 
            if(loopThread.IsAlive)
                loopThread.Abort();
             
            return !m_listener.IsListening;
        }
 
        void mainLoop()
        {
            while (true)
            {
                //wait for incoming requests
                HttpListenerContext ctx = m_listener.GetContext();
                 
                Stream str = ctx.Request.InputStream;
                TextReader tr = new StreamReader(str);
 
                SoapEnvelope env = new SoapEnvelope();
                env.LoadXml(tr.ReadToEnd());
                str.Close();
 
                //free the connection
                ctx.Response.Close();
 
                m_service.ProcessMessage(env);
            }
        }
 
        public void Dispose()
        {
            if (m_listener.IsListening)
            {
                Stop();
                m_listener.Close();
            }
        }
 
    }

This class contains a reference to the HttpListener and a reference to a Microsoft.Web.Services2.Messaging.SoapReceiver object, where a set of supported "Soap methods" are defined. The listener main loop is waiting for incoming Http requests to the "prefix" addresses defined in the constructors. As an example, a valid prefix could be something like that
m_listener.Prefixes.Add("http://localhost/ChatApp/");

An important (and courious) thing: if the prefix doesn't finish with "/" an exception will be thrown.
The HttpListener.GetContext() method, blocks the executing thread until a new http connection for the defined prefixes is stablished. Then, I build a new SoapEnvelope and load it with the posted xml. Finally, I call the SoapReceiver.ProcessMessage(SoapEnvelope env) method to pass the message through the pipeline and to call the suitable soap method.
The same application must also be capable of sending SoapEnvelope's by Http without IIS. The only important thing, is that the outgoing message has to pass through the output pipeline in order to build the internal soap message properly, and then the Pipeline.ProcessOutputMessage(SoapEnvelope env) method has to be called.

public void SendHttpMessage(string message, Address addr)
{
 
    SoapEnvelope env = new SoapEnvelope();
 
    Message m = new Message(message); //Message class implements IXmlElement
    env.Body.AppendChild(m.GetXml(env));
 
    env.Context.Addressing.From = new From(Settings.LocalHttpUri);
    env.Context.Addressing.Action = WSChat.ActionNames.GetMessage;
    env.Context.Addressing.Destination = new EndpointReference(addr);
 
    Pipeline.ProcessOutputMessage(env);
 
    WebRequest request = HttpWebRequest.Create(Destination.Address.Value);
    request.Method = "POST";
    request.ContentType = "text/xml";
    request.ContentLength = env.InnerXml.Length;
    StreamWriter sw = new StreamWriter(request.GetRequestStream());
    sw.Write(env.InnerXml);
    sw.Close();
     
    WebResponse response = request.GetResponse();
    response.Close();
}

Interchanged messages respond to a one-way pattern and then the http response is not considered.
And that's all!!... and it works!!.
Another important thing is to call the Dispose method of the HttpPort class when the main application finishes, to not hang the listener thread.
About the Author, Staff

You can write for Santry.com, just email us at [email protected] for more information.


blog comments powered by Disqus

 

Thank you for visiting our site, before you leave, please visit some of the areas or information you may have missed.

Popular Articles