Здравствуйте, Tanketka, Вы писали:
T>Только теперь это нужно сделать на C#, и многопоточной,
class Proxy
{
private Socket ListenerSocket;
List<ProxySession> Session = new List<ProxySession>();
public void Start( IPAddress ip, int port )
{
Socket ListenerSocket = new Socket();
ListenerSocket.Bind( new IPEndPoint( ip, port ) );
ListenerSocket.Listen();
ListenerSocket.BeginAccept( OnAccept );
}
private void OnAccept( IAsyncResult ar )
{
// создаем новую сессию на входящее соединение от браузера
ProxySession session = new ProxySession( ListenerSocket.EndAccept( ar ) );
// подписываемся на события
//session.OnClosed += OnSessionClosed;
//......
Session.Add( session );
session.Start();
}
}
class ProxySession
{
Socket ClientSocket;
Dictionnary<string,Socket> ServerSocket = new Dictionnary<string,Socket>();
public ProxySession( Socket socket ) { ClientSocket = socket; }
public void Start() { ClientSocket.BeginReceive( ...., OnReceive ); }
private void OnReceive( IAsynchResult ar )
{
try
{
ClientSocket.EndReceive( ar );
}
catch( SocketException )
{
// инициатором закрытия сессии может быть только клентсое соединение
// точнее, его разрыв
CloseSession();
return;
}
......
// тут смотрим запрос от браузера, вытаскиваем хост, на кот. идет запрос
// и если у нас нет такого в списке подключенных, то
// создаем соотв. новое подключение к веб-серверу
// причем это нужно делать при каждом запросе от клиента
// т.е. в рамках одной сессии может быть один конект от клиента,
// и много подключений к веб-серверам
Socket server = null;
if( !ServerSocket.TryGetValue( hostName, out server ) )
{
server = new Socket( ... );
ServerSocket.Add( hostName, server );
}
server.BeginSend( ..... );
ClientSocket.BeginReceive( ...., OnReceive );
}
}
код условный, разумеется, старался самое главное написать.
нужно еще добавить как минимум
синхронизацию общих ресурсов и обработку исключений
что бы сделать архитектуру гибче:
1. процесс передачи данных выделить в отдельный класс — трансмиттер,
кот. владеет 2-мя сокетами, и просто из одного читает и в другой пишет.
2. Сессия просто владеет списком этих "трансмиттеров"
3. операции по созданию сессий / трансмиттеров вынести в отдельные классы,
и юзать через интерфейсы, типа
new Proxy( (ISessionBuilder)( new ProxySessionBuilder( .. ));
new ProxySession( (IConnectionBuilder)( new ConnectionBuilder() ) );
это позволит сделать внутренюю структуру сессии более гибкой.
поясню: если между нашим прокси и веб-сервером сидит другой прокси,
нет смысла делать много клиентских подключений в одной сессии, достаточно одного.
для этого при создании прокси просто создаеются другой набор билдеров.
уже не говоря о том, что тогда этот прокси можно юзать не только для хттп.
4. прокси отвечает только за передачу данных в бинарном виде.
всю работу по анализу трафика тоже лучше выделить в отдельные классы, и тоже
передавать в сессию / прокси через интерфейсы.
при таком подходе реализация какого-либо протокола — всего лишь новый набор фильтров.
-----
мда, собирался покороче один ............