Есть код:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Proxy
{
class Program
{
public static ManualResetEvent allDone = new ManualResetEvent(false); //ручной ивент, чтобы не сбивались
static void Main(string[] args)
{
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
try
{
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint); //бинд
listener.Listen(1000); //максимальная очередь
while (true)
{
Console.WriteLine("Waiting for a connection");
// Set the event to nonsignaled state.
allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback),listener); //в отдельный поток обработку
allDone.WaitOne(); //ждем пока обработчик не начнется
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static void AcceptCallback(IAsyncResult ar)
{
byte[] bytes = new Byte[1024]; //сюда будем принимать (причем дважды .))
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Signal the main thread to continue.
allDone.Set();
string data = null; //отчищаем
// An incoming connection needs to be processed.
while (true)
{
bytes = new byte[1024];
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (bytesRec < 1024) //если не забили весь буфер
{
break;
}
}
//data хранит наш запрос, осталось распарсить .)
string[] data_strings = data.Split(new String[] { "\r\n" }, StringSplitOptions.None);
string data_host = null;
if (data_strings[0].Length > 3)
{
string data_address = data_strings[0].Substring(3, data_strings[0].IndexOf("HTTP") - 4).Trim(); //получаем адрес
}
if (data_strings[0].Length > 6)
{
data_host = data_strings[2].Substring(6, data_strings[2].Length - 6);
}
try
{
if (data_host != null)
{
IPHostEntry ipHostInfo = Dns.GetHostByName(data_host);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEndPoint = new IPEndPoint(ipAddress, 80);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //сокет соединения с удаленным сайтом
client.Connect(remoteEndPoint);
client.Send(Encoding.ASCII.GetBytes(data)); //отправляем то что получили от нашего пользователя
while (true)
{
bytes = new byte[1024];
int bytesRec = client.Receive(bytes);
ManualResetEvent s = new ManualResetEvent(false);
s.WaitOne(1000, false);
//Console.WriteLine(Encoding.ASCII.GetString(bytes, 0, bytesRec));
handler.Send(bytes);
if (bytesRec < 1024) //если не забили весь буфер
{
break;
}
}
client.Shutdown(SocketShutdown.Both);
client.Close();
}
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch(Exception e)
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
Console.WriteLine(e.ToString());
}
}
}
}
Если ставить брейкпоинт и пошагово выполнять проект то все с горем пополам работает, и страничка почастям грузится.
Если же бряк убирать и в динамическом режиме работать, ничего не работает.
Или загружается одна страница, вторая уже нет.
Проверка происходит следующим образом:
запускается браузер опера, у него прописывается вместо прокси ип сервера и пытается загрузить что либо.
Сервер (по идеи) должен получить по сокету запрос, его распарсить (вытащить оттуда ип хоста) и ему перенаправляет запрос, полученный ответ кидает обратно клиенту.
Спасибо.
Очень трудно написать даже простой корректный HTTP-сервер. Смешение парсинга и многопоточности в одной задаче даёт суровую проблему.
Поэтому вот тебе готовый прокси-сервер на C#, лицензия позволяет произвольно использовать в коммерческих/некоммерческих приложениях.
http://www.mentalis.org/soft/projects/proxy/
У тебя там превышено маскимально допустимое число багов.
R>Есть код:
R> if (bytesRec < 1024) //если не забили весь буфер
R> {
R> break;
R> }
А если забили весь буфер, то выкидываем полученные 1024 байта.
R> if (data_strings[0].Length > 6)
R> {
R> data_host = data_strings[2].Substring(6, data_strings[2].Length — 6);
R> }
Адрес хоста всегда последние 6 символов 2-го HTTP-заголовка.
R> ManualResetEvent s = new ManualResetEvent(false);
R> s.WaitOne(1000, false);
Квантовое програмирование. Создали событие, вот сидим ждём, что оно само перепрыгнет из не-сигнализированного состояния в сигнализированное.
Ну правильно, событие это же примитив, элементарная частица. Туннельный эффект на быстрых процессорах может обнаружиться.
R> handler.Send(bytes);
R> if (bytesRec < 1024) //если не забили весь буфер
R> {
R> break;
R> }
При чём здесь принимающий буфер?
Здравствуйте, mihailik, Вы писали:
R>> ManualResetEvent s = new ManualResetEvent(false);
R>> s.WaitOne(1000, false);
M>Квантовое програмирование. Создали событие, вот сидим ждём, что оно само перепрыгнет из не-сигнализированного состояния в сигнализированное.
M>Ну правильно, событие это же примитив, элементарная частица. Туннельный эффект на быстрых процессорах может обнаружиться.