[C#]实现一个多线程的 Web 代理服务器

[代码] Proxy.cs

/** 

C# Programming Tips & Techniques 

by Charles Wright, Kris Jamsa 

  

Publisher: Osborne/McGraw-Hill (December 28, 2001) 

ISBN: 0072193794 

*/

 

// Proxy.cs -- Implements a multi-threaded Web proxy server 

// 

//             Compile this program with the following command line: 

//                 C:>csc Proxy.cs 

using System;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.IO;

using System.Threading;

 

namespace nsProxyServer
{

    public class ProxyServer
{

        static public void Main(string[] args)
{

            int Port = 3125;

            if (args.Length > 0)
{

                try
{

                    Port = Convert.ToInt32(args[0]);

                }

                catch
{

                    Console.WriteLine("Please enter a port number.");

                    return;

                }

            }

            try
{

                // Create a listener for the proxy port 

                TcpListener sockServer = new TcpListener(Port);

                sockServer.Start();

                while (true)
{

                    // Accept connections on the proxy port. 

                    Socket socket = sockServer.AcceptSocket();

 

                    // When AcceptSocket returns, it means there is a connection. Create 

                    // an instance of the proxy server class and start a thread running. 

                    clsProxyConnection proxy = new clsProxyConnection(socket);

                    Thread thrd = new Thread(new ThreadStart(proxy.Run));

                    thrd.Start();

                    // While the thread is running, the main program thread will loop around 

                    // and listen for the next connection request. 

                }

            }

            catch (IOException e)
{

                Console.WriteLine(e.Message);

            }

        }

    }

 

    class clsProxyConnection
{

        public clsProxyConnection(Socket sockClient)
{

            m_sockClient = sockClient;

        }

        Socket m_sockClient; //, m_sockServer; 

        Byte[] readBuf = new Byte[1024];

        Byte[] buffer = null;

        Encoding ASCII = Encoding.ASCII;

 

        public void Run()
{

            string strFromClient = "";

            try
{

                // Read the incoming text on the socket/ 

                int bytes = ReadMessage(m_sockClient,

                                         readBuf, ref strFromClient);

                // If it's empty, it's an error, so just return. 

                // This will termiate the thread. 

                if (bytes == 0)

                    return;

                // Get the URL for the connection. The client browser sends a GET command 

                // followed by a space, then the URL, then and identifer for the HTTP version. 

                // Extract the URL as the string betweeen the spaces. 

                int index1 = strFromClient.IndexOf(' ');

                int index2 = strFromClient.IndexOf(' ', index1 + 1);

                string strClientConnection =

                      strFromClient.Substring(index1 + 1, index2 - index1);

 

                if ((index1 < 0) || (index2 < 0))
{

                    throw (new IOException());

                }

                // Write a messsage that we are connecting. 

                Console.WriteLine("Connecting to Site " +

                                   strClientConnection);

                Console.WriteLine("Connection from " +

                                   m_sockClient.RemoteEndPoint);

                // Create a WebRequest object. 

                WebRequest req = (WebRequest)WebRequest.Create

                                                     (strClientConnection);

                // Get the response from the Web site. 

                WebResponse response = req.GetResponse();

                int BytesRead = 0;

                Byte[] Buffer = new Byte[32];

                int BytesSent = 0;

 

                // Create a response stream object. 

                Stream ResponseStream = response.GetResponseStream();

 

                // Read the response into a buffer. 

                BytesRead = ResponseStream.Read(Buffer, 0, 32);

                StringBuilder strResponse = new StringBuilder("");

                while (BytesRead != 0)
{

                    // Pass the response back to the client 

                    strResponse.Append(Encoding.ASCII.GetString(Buffer,

                                        0, BytesRead));

                    m_sockClient.Send(Buffer, BytesRead, 0);

                    BytesSent += BytesRead;

                    // Read the next part of the response 

                    BytesRead = ResponseStream.Read(Buffer, 0, 32);

                }

            }

            catch (FileNotFoundException e)
{

                SendErrorPage(404, "File Not Found", e.Message);

            }

            catch (IOException e)
{

                SendErrorPage(503, "Service not available", e.Message);

            }

            catch (Exception e)
{

                SendErrorPage(404, "File Not Found", e.Message);

                Console.WriteLine(e.StackTrace);

                Console.WriteLine(e.Message);

            }

            finally
{

                // Disconnect and close the socket. 

                if (m_sockClient != null)
{

                    if (m_sockClient.Connected)
{

                        m_sockClient.Close();

                    }

                }

            }

            // Returning from this method will terminate the thread. 

        }

        // Write an error response to the client. 

        void SendErrorPage(int status, string strReason, string strText)
{

            SendMessage(m_sockClient, "HTTP/1.0" + " " +

                         status + " " + strReason + "\r\n");

            SendMessage(m_sockClient, "Content-Type: text/plain" + "\r\n");

            SendMessage(m_sockClient, "Proxy-Connection: close" + "\r\n");

            SendMessage(m_sockClient, "\r\n");

            SendMessage(m_sockClient, status + " " + strReason);

            SendMessage(m_sockClient, strText);

        }

 

        // Send a string to a socket. 

        void SendMessage(Socket sock, string strMessage)
{

            buffer = new Byte[strMessage.Length + 1];

            int len = ASCII.GetBytes(strMessage.ToCharArray(),

                                      0, strMessage.Length, buffer, 0);

            sock.Send(buffer, len, 0);

        }

 

        // Read a string from a socket. 

        int ReadMessage(Socket sock, byte[] buf, ref string strMessage)
{

            int iBytes = sock.Receive(buf, 1024, 0);

            strMessage = Encoding.ASCII.GetString(buf);

            return (iBytes);

        }

    }

}
(文/红薯)
来源于:http://www.oschina.net/code/snippet_12_660?from=rss

 


如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。