Для школьного проекта я делаю прокси для нескольких клиентов, который должен быть совместим с http 1.0, а не 1.1 (чтобы это было проще). Учитель сказал мне, что лучше сделать его полностью асинхронным. Так что я сделал полностью асинхронный прокси, есть только одна проблема. Это работает только тогда, когда я помещаю в него поток потоков, но это не делает его быстрее, но это единственный способ, позволяющий ему работать. Пожалуйста, помогите мне найти решение, и, может быть, кто-то знает, зачем ему нужен ThreadSep, чтобы он работал?
Учитель видит эту проблему каждый год, и единственное найденное решение - это спящий поток, поэтому учитель не нашел реального решения.
Сначала простой код для формы. Форма имеет кнопку запуска и текстовое поле для просмотра запроса и текстовое поле для просмотра ответов. После формы следует код для прокси.
Кстати, в Internet Explorer вы можете переключиться в режим http 1.0, так что это лучший способ для тестирования, также вам нужно заставить браузер прослушивать прокси-сервер (указанный в коде de).
using System;
using System.Windows.Forms;
using System.Threading;
namespace Proxy
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void startProxy_Click(object sender, EventArgs e)
{
var proxy = new Proxy(requestView, respondsView);
var thread = new Thread(new ThreadStart(proxy.StartProxy));
thread.IsBackground = true;
thread.Start();
startProxy.Enabled = false;
}
}
}
А теперь прокси, где проблема существует ...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace Proxy
{
class Proxy
{
private TextBox requestView;
private TextBox respondsView;
private delegate void UpdateLogCallback(string strMessage, TextBox txtView);
public const int PROXY_PORT = 5008;
public const int WEB_PROXY_PORT = 80;
public const int BACKLOG = 20;
public const int TIMEOUT = 4000;
public Proxy(TextBox _requestView, TextBox _respondsView)
{
requestView = _requestView;
respondsView = _respondsView;
}
public void StartProxy()
{
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Unspecified);
clientSocket.Bind(new IPEndPoint(IPAddress.Any, PROXY_PORT));
clientSocket.Listen(BACKLOG);
clientSocket.BeginAccept(HandleConnection, clientSocket);
}
private void HandleConnection(IAsyncResult iar)
{
Socket clientSocket = iar.AsyncState as Socket;
Socket client = clientSocket.EndAccept(iar);
clientSocket.BeginAccept(HandleConnection, clientSocket);
SocketData data = new SocketData() { SocketToClient = client };
client.BeginReceive(data.buffer, 0, SocketData.BUFFER_SIZE, SocketFlags.None, OnDataArrived, data);
}
private void OnDataArrived(IAsyncResult iar)
{
SocketData socketdata = iar.AsyncState as SocketData;
int bytesreceived = 0;
UpdateLogCallback uLC = new UpdateLogCallback(ReceiveMessages);
socketdata.SocketToClient.ReceiveTimeout = TIMEOUT;
try
{
bytesreceived = socketdata.SocketToClient.EndReceive(iar);
if (bytesreceived == SocketData.BUFFER_SIZE)
{
socketdata.sb.Append(ASCIIEncoding.ASCII.GetString(socketdata.buffer, 0, bytesreceived));
socketdata.SocketToClient.BeginReceive(socketdata.buffer, 0, SocketData.BUFFER_SIZE, SocketFlags.None, OnDataArrived, socketdata);
}
else
{
socketdata.sb.Append(ASCIIEncoding.ASCII.GetString(socketdata.buffer, 0, bytesreceived));
string strContent = socketdata.sb.ToString();
string[] testing = strContent.Split(' ');
if (testing[0] == "CONNECT")
{
//this is to prevent weird request to microsoft servers(???) also prevents ssl request...
}
else
{
IPEndPoint ip = new IPEndPoint(Dns.GetHostEntry(GetHostnameFromRequest(strContent)).AddressList[0], WEB_PROXY_PORT);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Unspecified);
server.Connect(ip);
requestView.Invoke(new UpdateLogCallback(uLC), new object[] { strContent, requestView });
server.Send(System.Text.ASCIIEncoding.ASCII.GetBytes(strContent));
socketdata.SocketToServer = server;
server.BeginReceive(socketdata.buffer2, 0, SocketData.BUFFER_SIZE, SocketFlags.None, OnWebsiteDataArrived, socketdata);
}
}
}
catch
{
socketdata.SocketToClient.Close();
}
}
private void OnWebsiteDataArrived(IAsyncResult iar)
{
SocketData socketdata = iar.AsyncState as SocketData;
int bytesreceived = 0;
UpdateLogCallback uLC = new UpdateLogCallback(ReceiveMessages);
socketdata.SocketToServer.ReceiveTimeout = TIMEOUT;
try
{
bytesreceived = socketdata.SocketToServer.EndReceive(iar);
Thread.Sleep(10);
if (bytesreceived == SocketData.BUFFER_SIZE)
{
socketdata.sb2.Append(ASCIIEncoding.ASCII.GetString(socketdata.buffer2, 0, bytesreceived));
socketdata.SocketToClient.Send(socketdata.buffer2, 0, SocketData.BUFFER_SIZE, SocketFlags.None);
socketdata.SocketToServer.BeginReceive(socketdata.buffer2, 0, SocketData.BUFFER_SIZE, SocketFlags.None, OnWebsiteDataArrived, socketdata);
}
else
{
socketdata.sb2.Append(ASCIIEncoding.ASCII.GetString(socketdata.buffer2, 0, bytesreceived));
respondsView.Invoke(new UpdateLogCallback(uLC), new object[] { socketdata.sb2.ToString(), respondsView });
socketdata.SocketToClient.Send(socketdata.buffer2, 0, bytesreceived, SocketFlags.None);
socketdata.SocketToClient.Close();
socketdata.SocketToServer.Close();
}
}
catch
{
socketdata.SocketToClient.Close();
}
}
private static string GetHostnameFromRequest(string strContent)
{
string[] host = strContent.Split(new string[] { "\r\n", ": " }, StringSplitOptions.RemoveEmptyEntries);
int check = Array.IndexOf(host, "Host");
return host[check + 1];
}
public void ReceiveMessages(string receiveMessages, TextBox txtView)
{
if (txtView.InvokeRequired)
{
UpdateLogCallback uLC = new UpdateLogCallback(ReceiveMessages);
txtView.Invoke(new UpdateLogCallback(uLC), new object[] { receiveMessages, txtView });
}
else
{
txtView.AppendText(receiveMessages);
}
}
public class SocketData
{
public SocketData()
{
this.packetlenght = 0;
}
public Socket SocketToClient { get; set; }
public Socket SocketToServer { get; set; }
public StringBuilder sb = new StringBuilder();
public StringBuilder sb2 = new StringBuilder();
public const int BUFFER_SIZE = 128;
public byte[] buffer = new byte[BUFFER_SIZE];
public byte[] buffer2 = new byte[BUFFER_SIZE];
public int packetlenght { get; set; }
}
}
}