CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 2 of 2
  1. #1
    Join Date
    Jul 2009
    Location
    London
    Posts
    13

    Lightbulb Asynchronous sockets

    Hello,
    First of all thanks for reading this. I am aiming to create a proxy server to overcome some authentication problems. The idea is to have the server handling the requests to a certain port, appending the right credentials, sending the authenticated request to the desirable address, and giving back the response (bytes) to the client.
    For that I created two sockets: a listening socket and a client socket for which I show here, the class definition.
    As I have a large volume of information on the requests, I am trying to use asynchronous sockets, so that I wont block the system waiting for an answer.
    The RequestState class contains the definitions for the state of the request, including a buffer.
    The process results in a serious of callbacks and the order of events is more or less this: the BeginGetResponse calls the RespCallback, where the webrequest to the desirable page is thrown, and it activates the BeginRead, that calls a ReadCallback. The readCallback fills the buffer and then I can either call a synchronous blocking send request (which does not work on IE, for e.g.) or call BeginSend with a callback function. The BeginSend also does not work, since the callback (finish) terminates without actualy sending all the information.
    Any tips about what I'm doing wrong?
    Thanks in advance,
    Jo

    Code:
    using System;
    using System.Net;
    using System.IO;
    using System.Net.Security;
    using System.Net.Sockets;
    using System.Threading;
    using System.Text;
    
    namespace TEST
    {
        // The RequestState class passes data across async calls.
        public class RequestState
        {
            public int BufferSize = 1024;
            public byte[] RequestData;
            public byte[] BufferRead;
            public WebRequest Request;
            public Stream ResponseStream;
            public WebResponse Response;
            public Socket aSocket;
    
            public RequestState()
            {
                BufferRead = new byte[BufferSize];
                RequestData = new byte[0];
                Request = null;
                aSocket = null;
                //Response = null;
                ResponseStream = null;
            }
        }
        ///////////////////////////////////////////////////////
    
        public delegate void DestroyDelegate_(ProxyClient client);
        public class ProxyClient : IDisposable
        {
            //public static ManualResetEvent allDone = new ManualResetEvent(false);
            const string myUri="http://DEV309.Dev.cadcorp.net:4326/KmlService/Kml.serv?REQUEST=GetCapabilities";
            //const string myUri = "http://localhost/hello.htm";
    
            public ProxyClient(Socket ClientSocket, DestroyDelegate_ Destroyer, IPEndPoint MapTo, CredentialCache credCache)
            {
                this.ClientSocket = ClientSocket;
                this.Destroyer = Destroyer;
                this.MapTo = MapTo;
                this.m_credCache = credCache;
                this.m_sendDone = new ManualResetEvent(true);
            }
    
            private IPEndPoint MapTo
            {
                get
                {
                    return m_MapTo;
                }
                set
                {
                    if (value == null)
                        throw new ArgumentNullException();
                    m_MapTo = value;
                }
            }
    
            internal Socket ClientSocket
            {
                get
                {
                    return m_ClientSocket;
                }
                set
                {
                    if (m_ClientSocket != null)
                        m_ClientSocket.Close();
                    m_ClientSocket = value;
                }
            }
    
            public void Dispose()
            {
                try
                {
                    ClientSocket.Shutdown(SocketShutdown.Both);
                }
                catch { }
                //Close the sockets
                if (ClientSocket != null)
                    ClientSocket.Close();
                //Clean up
                ClientSocket = null;
                if (Destroyer != null)
                    Destroyer(this);
            }
     
            /////////////////////////////// WebRequest //////////////////////////////////////////////////////
                private void ReadCallBack(IAsyncResult asyncResult)
                {
                    try
                    {
                        RequestState myRequestState = (RequestState)asyncResult.AsyncState;
                        Stream responseStream = myRequestState.ResponseStream;
                        int read = responseStream.EndRead(asyncResult);
                        if (read > 0)
                        {
                            //Resize Buffer
                            byte[] newBuffer = new byte[myRequestState.RequestData.Length + read];
                            Buffer.BlockCopy(myRequestState.RequestData, 0, newBuffer, 0, myRequestState.RequestData.Length);
                            Buffer.BlockCopy(myRequestState.BufferRead, 0, newBuffer, myRequestState.RequestData.Length, read);
                            myRequestState.RequestData = newBuffer;
    
                            IAsyncResult asynchronousResult =
                               responseStream.BeginRead(myRequestState.BufferRead, 0, myRequestState.BufferSize,
                                 new AsyncCallback(ReadCallBack), myRequestState);
    
                        }
                        else
                        {
                            if (myRequestState.RequestData.Length > 0)
                            {
                                myRequestState.aSocket.BeginSend(myRequestState.RequestData, 0, myRequestState.RequestData.Length,SocketFlags.None, new AsyncCallback(Finish), myRequestState);
    /*
                                int i = myRequestState.aSocket.Send(myRequestState.RequestData, 0, myRequestState.RequestData.Length, SocketFlags.None);
                                System.Diagnostics.Debug.Write("Sent {0} bytes."+ i+"\n");
                                Dispose();
                                myRequestState.ResponseStream.Close();
     */
                            }
                            //responseStream.Close();
                            //myRequestState.aSocket.Shutdown(SocketShutdown.Both);
                            //myRequestState.aSocket.Close();
                            //allDone.Set();
                        }
                    }
                    catch (SocketException ex)
                    {
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
                        Dispose();
                    }
                }
    
                private void Finish(IAsyncResult asyncResult)
                {
                    try
                    {
                        RequestState myRequestState = (RequestState)asyncResult.AsyncState;
                        Socket mySocket = myRequestState.aSocket;
    
                        int Ret = mySocket.EndSend(asyncResult);
                        if (Ret <= 0)
                        {
                            Dispose();
                            myRequestState.ResponseStream.Close();
                       }
                        //m_sendDone.Set();
                    }
                    catch (SocketException ex)
                    {
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
                        Dispose();
                    }
                }
    
                private void RespCallback(IAsyncResult asynchronousResult)
                {
                    try
                    {
                        RequestState myRequestState = (RequestState)asynchronousResult.AsyncState;
    
                        WebRequest myWebRequest1 = myRequestState.Request;
                        myRequestState.Response = myWebRequest1.EndGetResponse(asynchronousResult);
    
                        Stream responseStream = myRequestState.Response.GetResponseStream();
                        myRequestState.ResponseStream = responseStream;
    
                        IAsyncResult asynchronousResultRead =
                        responseStream.BeginRead(myRequestState.BufferRead, 0, myRequestState.BufferSize,
                        new AsyncCallback(ReadCallBack), myRequestState);
                    }
                    catch (SocketException ex)
                    {
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
                        Dispose();
                    }
                }
    
                public void StartHandshake()
                {
                    try
                    {
                        WebRequest request = (HttpWebRequest)WebRequest.Create(myUri);
                        request.Credentials = m_credCache;//CredentialCache.DefaultCredentials;
                        RequestState myRequestState = new RequestState();
                        myRequestState.Request = request;
                        myRequestState.aSocket = ClientSocket;
    
                        // Issue the async request.
                        IAsyncResult r = (IAsyncResult)request.BeginGetResponse(
                           new AsyncCallback(RespCallback), myRequestState);
    
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
                        Dispose();
                    }
                }
    
                private CredentialCache m_credCache;
                private DestroyDelegate_ Destroyer;
                private Socket m_ClientSocket;
                private IPEndPoint m_MapTo;
                private ManualResetEvent m_sendDone;
        }

  2. #2
    Join Date
    Jul 2009
    Location
    London
    Posts
    13

    Re: Asynchronous sockets

    I decided that I didnt need such a complicated solution; I didnt need one asynchronous listening socket and an asynchronous client socket;
    In fact, all I need is a listening socket that is asynchronous (otherwise it will block the main thread) and I can stream the request in the same class (multithreading is not really an issue, since I wont have multiple requests to the server); I also found it much more convenient to use the HttpListener class;
    Here is the code I ended up with:

    Code:
    using System;
    using System.Text;
    using System.Net;
    using System.IO;
    
    namespace TEST
    {
        public delegate void delReceiveWebRequest(HttpListenerContext Context);
    
        public class ProxyServer
        {
            private int m_port = 47809;//Starts with this port, which according to IANA is for private use!
            private static string localhost = "127.0.0.1";
            const int BUFFER_SIZE = 1024;
            public string m_server;
            protected HttpListener m_listener;
            private CredentialCache m_credCache;
            public event delReceiveWebRequest ReceiveWebRequest;
    
            public ProxyServer(string server, CredentialCache credCache)
            {
                this.m_server = server;
                this.m_credCache = credCache;
            }
    
            public string Address()
            {
                return "http://" + localhost + ":" + m_port.ToString() + "/";
            }
    
            /// <summary>
            /// Starts the Web Service
            /// </summary>
            /// <param name="UrlBase">
            /// A Uri that acts as the base that the server is listening on.
            /// Format should be: http://127.0.0.1:8080/ or http://127.0.0.1:8080/somevirtual/
            /// Note: the trailing backslash is required! For more info see the
            /// HttpListener.Prefixes property on MSDN.
            /// </param>
    
            public bool Start()
            {
                try
                {
                    this.m_listener = new HttpListener();
                    this.m_listener.Prefixes.Add(Address());
                    this.m_listener.Start();
    
                    IAsyncResult result = this.m_listener.BeginGetContext(new AsyncCallback(WebRequestCallback), this.m_listener);
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(e.ToString());
                    System.Diagnostics.Debug.WriteLine("Could not connect on port " + m_port.ToString() + "!");
                    m_port++;
                    return false;
                }
    
                System.Diagnostics.Debug.WriteLine("Listening socket on port " + m_port);
                return true;
            }
    
            /// <summary>
            /// Shut down the Web Service
            /// </summary>
    
            public void Stop()
            {
                if (m_listener != null)
                {
                    this.m_listener.Close();
                    this.m_listener = null;
                    System.Diagnostics.Debug.WriteLine("Proxy stopped on port " + m_port.ToString() + "!");
                }
            }
    
            protected void WebRequestCallback(IAsyncResult result)
            {
                if (this.m_listener == null)
                    return;
    
                // Get out the context object
                HttpListenerContext context = this.m_listener.EndGetContext(result);
    
                // *** Immediately set up the next context
                this.m_listener.BeginGetContext(new AsyncCallback(WebRequestCallback), this.m_listener);
    
                if (this.ReceiveWebRequest != null)
                    this.ReceiveWebRequest(context);
    
                this.ProcessRequest(context);
            }
    
            protected virtual void ProcessRequest(HttpListenerContext Context)
            {
                string uri=Context.Request.RawUrl;
    
                this.m_server = this.m_server.Remove(this.m_server.Length - 1);
                string address = this.m_server + uri;
                WebRequest request = (HttpWebRequest)WebRequest.Create(address);
                request.Credentials = m_credCache;//CredentialCache.DefaultCredentials;
                StringBuilder RequestData = new StringBuilder(String.Empty);
    
                WebResponse myWebResponse = request.GetResponse();
                Stream ReceiveStream = myWebResponse.GetResponseStream();
    
                Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
    
                // Pipe the stream to a higher level stream reader with the required encoding format. 
                StreamReader readStream = new StreamReader(ReceiveStream, encode);
                Char[] read = new Char[BUFFER_SIZE];
    
                // Read 1024 characters at a time.    
                int count = readStream.Read(read, 0, BUFFER_SIZE);
    
                HttpListenerResponse response = Context.Response;
                System.IO.Stream output = response.OutputStream;
    
                while (count > 0)
                {
                    // Dump the 1024 characters on a string and display the string onto the console.
                    String str = new String(read, 0, count);
    
                    output.Write(encode.GetBytes(str), 0, encode.GetBytes(str).Length);
                    count = readStream.Read(read, 0, BUFFER_SIZE);
                }
    
                output.Close();
            }
        }
    
    }

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured