#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2010
    Location
    Location : Location : Location
    Posts
    66
    Rep Power
    0

    C# simple proxy server


    Starter here, I'm trying to code a simple proxy server in C# using sockets (working on GET only atm), the code below "works" it does show the webpage via my proxy running but it's slow most of the time and always end up with socket exception which I have no idea how to deal with...

    reference: http://royjin.wordpress.com/2010/08/13/c-basic-socket-programming-building-proxy-server/

    Code:
    class ProxyServer {
        static void Main(string[] args) {
            const int DEFAULT_PORT_NO = 27015;
            int port = -1;
            if(args.Length > 0 && args[0] != null) {
                port = Int32.Parse(args[0]); 
            } else if(port == -1) {
                port = DEFAULT_PORT_NO;
            }
    
            const int BACKLOG = 10;
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ipAddress = IPAddress.Loopback;
            IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
            listener.Bind(localEndPoint);
            listener.Listen(BACKLOG);
            Console.WriteLine(localEndPoint.ToString() + " Listening...\n");
    
            while(true) {
                Socket listenSocket = listener.Accept();
                RequestHandler requestHandler = new RequestHandler(listenSocket);
                Thread requestThread = new Thread(new ThreadStart(requestHandler.handle));
                requestThread.Start();
            }
        }
    }
    
    class RequestHandler {
        private Socket serverSocket;
    
        public RequestHandler(Socket s) {
            serverSocket = s;
        }
    
        public void handle() {
            string header = getHeader(serverSocket);
            string host = getHost(header);
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress[] addresslist = Dns.GetHostAddresses(new Uri(host).Host);
            IPEndPoint remoteEndPoint = new IPEndPoint(addresslist[0], new Uri(host).Port);
            clientSocket.Connect(remoteEndPoint);
            sendRequest(clientSocket, header);
    
            header = getHeader(clientSocket);
            sendRequest(serverSocket, header);
            const int BUFFER_SIZE = 1024;
            byte[] buffer = new byte[BUFFER_SIZE];
            int receivedBytes = clientSocket.Receive(buffer);
            while(receivedBytes > 0) {
                serverSocket.Send(buffer, receivedBytes, SocketFlags.None);
                receivedBytes = clientSocket.Receive(buffer);
            }
    
            serverSocket.Shutdown(SocketShutdown.Both);
            serverSocket.Close();
        }
    
        string getHeader(Socket s) {
            string header = "";
            while(true){
                byte[] bytes = new byte[1];
                int bytesRec = s.Receive(bytes);
                header += System.Text.Encoding.ASCII.GetString(bytes, 0, bytesRec);
                if (header.IndexOf("\r\n\r\n") > -1 || header.IndexOf("\n\n") > -1){
                    break;
                }
            }
            return header;
        }
    
        string getHost(String h) {
            return h.Split(new char[] {'\n'})[0].Split(new char[] {' '})[1];
        }
    
        void sendRequest(Socket s, string h) {
            byte[] bytesSent = System.Text.Encoding.ASCII.GetBytes(h);
            s.Send(bytesSent, bytesSent.Length, SocketFlags.None);
        }
    
    }
    Pointers would be great...
  2. #2
  3. No Profile Picture
    I haz teh codez!
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Dec 2003
    Posts
    2,549
    Rep Power
    2337
    it's slow most of the time
    Probably because you're:

    1. Spawning a new thread with every request (expensive -- should use a ThreadPool)
    2. String concatenation in C# is expensive, because strings are immutable so it's continually creating new strings to do this. Look into using StringBuilder for such tasks.
    3. Reading one byte at a time from the client.

    always end up with socket exception which I have no idea how to deal with
    Well you don't handle any exceptions, and it's a bit hard to give advice when you don't bother to tell us what is the exception.
    I ♥ ManiacDan & requinix

    This is a sig, and not necessarily a comment on the OP:
    Please don't be a help vampire!
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2010
    Location
    Location : Location : Location
    Posts
    66
    Rep Power
    0
    Originally Posted by ptr2void
    Probably because you're:

    1. Spawning a new thread with every request (expensive -- should use a ThreadPool)
    2. String concatenation in C# is expensive, because strings are immutable so it's continually creating new strings to do this. Look into using StringBuilder for such tasks.
    3. Reading one byte at a time from the client.



    Well you don't handle any exceptions, and it's a bit hard to give advice when you don't bother to tell us what is the exception.
    thanks for the reply, i will get back to this thread with updates!
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    2
    Rep Power
    0

    more efficient code


    For true proxy, just as if the source connects directly to the destination:

    After accepting the socket you should be connecting a destination socket, then hook up an event listener on both the source socket and destination socket for incoming data.
    this will convert your solution to an async model. performance is much better. in the data arrived event from the source socket take the incoming bytes and send it out the destination socket. on the event from the destination send the bytes out the source socket. This creates duplex transferal of data. Also have event listeners for disconnect on both source and destionation sockets. Whichever disconnect first then disconnect the other socket.

IMN logo majestic logo threadwatch logo seochat tools logo