如何修复我的异步tcp代理服务器响应,使其正常工作?

问题描述:

全部!

我在异步套接字上编写代理服务器用于教育目的并坚持到位,如果我不使用,我的浏览器会以不同方式处理某些网站的响应代理,对于其中一些我根本看不到响应,虽然我在控制台中看到,该请求已发送并收到响应。

这是服务器的代码。

你能告诉我,有什么问题以及我可以做些什么来改善服务器?



Hi, all!
I am writing proxy server on asynchronous sockets for educational purposes and stuck at the point, that my browser treat some web-sites' response different way if i don't use the proxy, for some of them i don't see response at all, though i see in console, that request was sent and response was received.
Here is the code of server.
Could you advise, what is wrong and what i can do to improve server?

Quote:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncTcpServer
{
    internal class AsyncTcpServer
    {
        private bool syncmode;
        private Socket listenSocket;
        private const int port_ = 9999;
        private const int bufferSendSize = 8192;
        private const int bufferSize = 65536;//1048576;
        private LingerOption lo;
        private AutoResetEvent autoEvent;

        private static void Main(string[] args)
        {
            // Create the socket which listens for incoming connections.
            var server = new AsyncTcpServer();
            ThreadPool.SetMinThreads(100, 100);
            ThreadPool.SetMaxThreads(3000, 3000);
            server.StartServer();
            Console.WriteLine("Press smth to stop server");
            Console.Read();
        }

        private void StartServer()
        {
            autoEvent = new AutoResetEvent(true);
            var addressList = Dns.GetHostEntry(Environment.MachineName).AddressList;
            foreach (var ipAddress in addressList)
            {
                Console.WriteLine(ipAddress);
            }
            int choice;
            Console.WriteLine("Choose ip");
            int.TryParse(Console.ReadLine(), out choice);
            Console.WriteLine("Choose sync mode or not");
            bool.TryParse(Console.ReadLine(), out syncmode);
            var localEndPoint = new IPEndPoint(addressList[choice], port_);

            // Get host related information.
            listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            lo = new LingerOption(false, 0);
            listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
            // Get endpoint for the listener.
            if (localEndPoint.AddressFamily == AddressFamily.InterNetworkV6)
            {
                // Set dual-mode (IPv4 & IPv6) for the socket listener.
                // 27 is equivalent to IPV6_V6ONLY socket option in the winsock snippet below,
                // based on http://blogs.msdn.com/wndp/archive/2006/10/24/creating-ip-agnostic-applications-part-2-dual-mode-sockets.aspx
                listenSocket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName)27, false);
                listenSocket.Bind(new IPEndPoint(IPAddress.IPv6Any, localEndPoint.Port));
            }
            else
            {
                // Associate the socket with the local endpoint.
                Console.WriteLine(localEndPoint);
                listenSocket.Bind(localEndPoint);
            }

            // Start the server.
            listenSocket.Listen(500);
            if (syncmode)
            {
                listenSocket.BeginAccept(EndAccept, listenSocket);
            }
            else
            {
                for (int i = 0; i < 200; i++)
                {
                    listenSocket.BeginAccept(EndAccept, listenSocket);
                } 
            }
        }

        private void EndAccept(IAsyncResult result)
        {
            if (syncmode)
            {
                autoEvent.WaitOne();    
            }
            
            Console.WriteLine("ExecuteRequest");
            var server = result.AsyncState as Socket;
            if (server != null)
            {
                try
                {
                    var myClient = server.EndAccept(result);
                    myClient.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
                    var token = new Token(myClient, bufferSendSize);

                    myClient.BeginReceive(token.Buffer, 0, token.Buffer.Length, SocketFlags.None, EndReceive, token);
                }
                catch (SocketException e)
                {
                    Console.WriteLine(e.Message);
                    autoEvent.Set();
                    listenSocket.BeginAccept(EndAccept, listenSocket);
                }

            }
            else
            {
                StartServer();
            }
        }

        private void EndReceive(IAsyncResult result)
        {
            var token = result.AsyncState as Token;
            if (token == null) return;
            
            var myClient = token.Connection;
            var length = myClient.EndReceive(result);

            Console.WriteLine("Process request from {0}", myClient.RemoteEndPoint as IPEndPoint);
            byte[] httpRequest = new byte[length];
            Array.Copy(token.Buffer, httpRequest, length);
            token.Buffer = httpRequest;
            var endPoint = ProcessReceive(token);
            if (endPoint == null)
            {
                return;
            }
            // connecting to remote socket
            var rerouting = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            {
                SendBufferSize = bufferSendSize,
                ReceiveBufferSize = bufferSize
            };
            rerouting.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
            token.RemoteConnection = rerouting;
            rerouting.BeginConnect(endPoint, EndConnect, token);       
        }

        private IPEndPoint ProcessReceive(Token token)
        {
            // searching host and port
            var client = token.Connection;
            var regex = new Regex(@"Host: (((?<host>.+?):(?<port>\d+?))|(?<host>.+?))\s+", RegexOptions.Multiline | RegexOptions.IgnoreCase);
            var match = regex.Match(System.Text.Encoding.UTF8.GetString(token.Buffer));
            string host = match.Groups["host"].Value;
            var endPoint = client.RemoteEndPoint as IPEndPoint;
            if (host.Equals(string.Empty))
            {
                listenSocket.BeginAccept(EndAccept, listenSocket);
                return null;
            }
            Console.WriteLine("requesting {0} from {1}", host, endPoint);

            int port = 0;
            // use 80 port as default
            if (!int.TryParse(match.Groups["port"].Value, out port))
            {
                port = 80;
            }

            // receive ip from host
            const string ipPattern = @"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
            bool isIp = Regex.IsMatch(host, ipPattern);
            
            // creating access point
            IPAddress ip;
            if (isIp)
            {
                ip = IPAddress.Parse(host);
            }
            else
            {
                IPHostEntry hostEntry = Dns.GetHostEntry(host);
                ip = hostEntry.AddressList[hostEntry.AddressList.Count() - 1];
            }
            return new IPEndPoint(ip, port);
        }

        private void EndConnect(IAsyncResult result)
        {
            var token = result.AsyncState as Token;
            if (token == null) return;
            try
            {
                var rerouting = token.RemoteConnection;
                rerouting.EndConnect(result);
                Console.WriteLine("Connected to {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint);
                rerouting.BeginSend(token.Buffer, 0, token.Buffer.Length, SocketFlags.None, EndSend, token);          
            }
            catch (SocketException e)
            {
                token.Dispose();
                Console.WriteLine(e.Message);
                autoEvent.Set();
                listenSocket.BeginAccept(EndAccept, listenSocket);
            }
            
        }

        private void EndSend(IAsyncResult result)
        {
            var token = result.AsyncState as Token;
            if (token == null) return;
            try
            {
                var length = token.RemoteConnection.EndSend(result);
                Console.WriteLine("Sent{1} bytes to {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint, length);
                var newtoken = new Token(token, bufferSize);
                token.RemoteConnection.BeginReceive(newtoken.Buffer, 0, newtoken.Buffer.Length, SocketFlags.None, EndReceiveRemote, newtoken);
            }
            catch (SocketException e)
            {
                token.Dispose();
                Console.WriteLine(e.Message);
                autoEvent.Set();
                listenSocket.BeginAccept(EndAccept, listenSocket);
            }
        }

        private void EndReceiveRemote(IAsyncResult result)
        {
            var token = result.AsyncState as Token;
            if (token == null) return;
            try
            {
                var length = token.RemoteConnection.EndReceive(result);
                Console.WriteLine("Received {1} bytes from {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint, length);
                var httpResponse = token.Buffer;
                if (httpResponse == null || httpResponse.Length <= 0) return;
                if (!syncmode)
                {
                    autoEvent.WaitOne();   
                }
                token.Connection.BeginSend(token.Buffer, 0, length, SocketFlags.None, EndSendToClient, token); 
            }
            catch (SocketException e)
            {
                token.Dispose();
                autoEvent.Set();
                Console.WriteLine(e.Message);
                listenSocket.BeginAccept(EndAccept, listenSocket);
            }
        }

        private void EndSendToClient(IAsyncResult result)
        {
            var token = result.AsyncState as Token;
            if (token == null) return;
            var length = token.Connection.EndSend(result);
            Console.WriteLine("Sent{1} bytes to {0}", token.Connection.RemoteEndPoint as IPEndPoint, length);
            token.Dispose();
            autoEvent.Set();
            listenSocket.BeginAccept(EndAccept, listenSocket);
        }
    }
}




;
bool isIp = Regex.IsMatch(host,ipPattern);

// 创建访问点
IPAddress ip;
if (isIp)
{
ip = IPAddress.Parse(host);
}
else
{
IPHostEntry hostEntry = Dns.GetHostEntry(host);
ip = hostEntry.AddressList [hostEntry.AddressList.Count() - 1 ];
}
return new IPEndPoint(ip,port);
}

private void EndConnect(IAsyncResult结果)
{
var token = result.AsyncState as Token;
if (token == null return 跨度>;
尝试
{
var rerouting = token.RemoteConnection;
rerouting.EndConnect(result);
Console.WriteLine( 已连接到{0},token.RemoteConnection.RemoteEndPoint as
IPEndPoint);
rerouting.BeginSend(token.Buffer, 0 ,token.Buffer.Length,SocketFlags.None,EndSend,token);
}
catch (SocketException e)
{
token.Dispose();
Console.WriteLine(e.Message);
autoEvent.Set();
listenSocket.BeginAccept(EndAccept,listenSocket);
}

}

private void EndSend(IAsyncResult结果)
{
var token = result.AsyncState as 令牌;
if (token == null return 跨度>;
尝试
{
var length = token.RemoteConnection.EndSend (结果);
Console.WriteLine( 将{1}个字节发送到{0},令牌。 RemoteConnection.RemoteEndPoint as IPEndPoint,length);
var newtoken = new 令牌(token,bufferSize);
token.RemoteConnection.BeginReceive(newtoken.Buffer, 0 ,newtoken.Buffer.Length,SocketFlags.None,EndReceiveRemote,newtoken);
}
catch (SocketException e)
{
token.Dispose();
Console.WriteLine(e.Message);
autoEvent.Set();
listenSocket.BeginAccept(EndAccept,listenSocket);
}
}

私有 void EndReceiveRemote( IAsyncResult结果)
{
var token = result.AsyncState as Token;
if (token == null return 跨度>;
尝试
{
var length = token.RemoteConnection.EndReceive (结果);
Console.WriteLine( 从{0}接收{1}个字节,令牌。 RemoteConnection.RemoteEndPoint as IPEndPoint,length);
var httpResponse = token.Buffer;
if (httpResponse == null || httpResponse.Length < = 0 return ;
if (!syncmode)
{
autoEvent.WaitOne();
}
token.Connection.BeginSend(token.Buffer, 0 ,length,SocketFlags.None,EndSendToClient,token);
}
catch (SocketException e)
{
token.Dispose();
autoEvent.Set();
Console.WriteLine(e.Message);
listenSocket.BeginAccept(EndAccept,listenSocket);
}
}

私有 void EndSendToClient( IAsyncResult结果)
{
var token = result.AsyncState as Token;
if (token == null return 跨度>;
var length = token.Connection.EndSend(result);
Console.WriteLine( 将{1}个字节发送到{0},令牌。 Connection.RemoteEndPoint as IPEndPoint,length);
token.Dispose();
autoEvent.Set();
listenSocket.BeginAccept(EndAccept,listenSocket);
}
}
}
"; bool isIp = Regex.IsMatch(host, ipPattern); // creating access point IPAddress ip; if (isIp) { ip = IPAddress.Parse(host); } else { IPHostEntry hostEntry = Dns.GetHostEntry(host); ip = hostEntry.AddressList[hostEntry.AddressList.Count() - 1]; } return new IPEndPoint(ip, port); } private void EndConnect(IAsyncResult result) { var token = result.AsyncState as Token; if (token == null) return; try { var rerouting = token.RemoteConnection; rerouting.EndConnect(result); Console.WriteLine("Connected to {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint); rerouting.BeginSend(token.Buffer, 0, token.Buffer.Length, SocketFlags.None, EndSend, token); } catch (SocketException e) { token.Dispose(); Console.WriteLine(e.Message); autoEvent.Set(); listenSocket.BeginAccept(EndAccept, listenSocket); } } private void EndSend(IAsyncResult result) { var token = result.AsyncState as Token; if (token == null) return; try { var length = token.RemoteConnection.EndSend(result); Console.WriteLine("Sent{1} bytes to {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint, length); var newtoken = new Token(token, bufferSize); token.RemoteConnection.BeginReceive(newtoken.Buffer, 0, newtoken.Buffer.Length, SocketFlags.None, EndReceiveRemote, newtoken); } catch (SocketException e) { token.Dispose(); Console.WriteLine(e.Message); autoEvent.Set(); listenSocket.BeginAccept(EndAccept, listenSocket); } } private void EndReceiveRemote(IAsyncResult result) { var token = result.AsyncState as Token; if (token == null) return; try { var length = token.RemoteConnection.EndReceive(result); Console.WriteLine("Received {1} bytes from {0}", token.RemoteConnection.RemoteEndPoint as IPEndPoint, length); var httpResponse = token.Buffer; if (httpResponse == null || httpResponse.Length <= 0) return; if (!syncmode) { autoEvent.WaitOne(); } token.Connection.BeginSend(token.Buffer, 0, length, SocketFlags.None, EndSendToClient, token); } catch (SocketException e) { token.Dispose(); autoEvent.Set(); Console.WriteLine(e.Message); listenSocket.BeginAccept(EndAccept, listenSocket); } } private void EndSendToClient(IAsyncResult result) { var token = result.AsyncState as Token; if (token == null) return; var length = token.Connection.EndSend(result); Console.WriteLine("Sent{1} bytes to {0}", token.Connection.RemoteEndPoint as IPEndPoint, length); token.Dispose(); autoEvent.Set(); listenSocket.BeginAccept(EndAccept, listenSocket); } } }





评论中的讨论看起来远远超出了Quick Questions& amp;解答。你真的需要从一开始就仔细地设计服务器和客户端部分;所以专注于你的问题可能不那么有用。对于一些非常相关的想法,请参阅我过去的答案:

套接字编程中的业余问题 [ ^ ],>
来自同一端口号码的多个客户端 [ ^ ]。



请考虑一下,如果有的话,请提出后续问题。



我不认为你是否愿意接受抛弃异步通信的想法。它应该通过使用线程来完成,每个都应该使用同步,阻塞网络操作。为什么?对我来说,这很清楚。我在过去的答案中分享了一些解释,请阅读:

异步和并发WCF服务调用 [ ^ ],

TcpListener,TcpClient,在Visual Basic 2005中Ping [ ^ ],

多线程问题? !!! [ ^ ]。



-SA
The discussion in comments looks going well beyond the format of Quick Questions & Answers. You really need to design the server and client parts thoughtfully from the very beginning; so focusing on just your questions may not be so helpful. For some very relevant ideas, please see my past answers:
an amateur question in socket programming[^],
Multple clients from same port Number[^].

Please think about it and then ask follow-up questions if you have any.

I don't see if you are read to embrace throwing out the idea of asynchronous communications. It should be done asynchronous by using thread, each of those should use synchronous, blocking network operations. Why? To me, this is quite clear. I shared some explanations in my past answers, please read them:
Asynchronous and Concurrent WCF service Calls[^],
TcpListener, TcpClient, Ping in Visual Basic 2005[^],
problem in multithreading ? !!![^].

—SA