本来意图是想写个工具放到服务器里代理一下上秋秋的。
没想到N台(电信/联通/移动)的服务器都把端口全封了。
所以以下代码是在本地测试代理网页访问通过。
说下思路再上代码及下载:
其实一句话就是:产生两个Soket,一个负责接收请求和回发请求,另一个负责中转的去请求和接收。
重点一句话就是:每个请求产生一个线程处理,处理时关键是的延时处理(不然数据接收不全)。
现在上代码,Proxy自定义类:
Proxy
using
System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
//by 路过秋天
namespace TCPProxy
{
public class Proxy
{
Socket clientSocket; // 接收和返回
Byte[] read = null ; // 存储来自客户端请求数据包
Byte[] recvBytes = null ; // 存储中转请求返回的数据
public Proxy(Socket socket)
{
clientSocket = socket;
recvBytes = new Byte[ 1024 * 1024 ];
clientSocket.ReceiveBufferSize = recvBytes.Length;
clientSocket.SendBufferSize = recvBytes.Length;
clientSocket.SendTimeout = 10000 ;
clientSocket.ReceiveTimeout = 10000 ;
}
public void Run()
{
#region 获取客户端请求数据
string clientmessage = "" ;
read = new byte [clientSocket.Available];
int bytes = ReadMessage(read, ref clientSocket, ref clientmessage);
if (bytes == 0 )
{
Write( " 读取不到数据! " );
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
return ;
}
int port = 80 ;
string url = GetUrl(clientmessage, port);
#endregion
try
{
#region IP解析获取
IPHostEntry IPHost = Dns.GetHostEntry(url);
Write( " -----------------------------请求开始--------------------------- " );
Write( " http:// " + IPHost.HostName);
string [] aliases = IPHost.Aliases;
IPAddress[] address = IPHost.AddressList; // 解析出要访问的服务器地址
Write( " IP地址: " + address[ 0 ]);
#endregion
#region 创建中转Socket及建立连接
IPEndPoint ipEndpoint = new IPEndPoint(address[ 0 ], port);
Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 创建连接Web服务器端的Socket对象
IPsocket.Connect(ipEndpoint);
// Socket连Web接服务器
if (IPsocket.Connected)
{
Write( " Socket 正确连接! " );
}
#endregion
#region 发送中转请求
IPsocket.Send(read, 0 );
Write( " 发送字节: " + read.Length);
#endregion
#region 接收中转请求数据
int length = 0 , count = 0 ;
do
{
length = IPsocket.Receive(recvBytes, count, IPsocket.Available, 0 );
count = count + length;
Write( " 正在接收数据... " + length);
System.Threading.Thread.Sleep( 100 ); // 关键点,请求太快数据接收不全
}
while (IPsocket.Available > 0 );
#endregion
#region 关闭中转请求Socket
IPsocket.Shutdown(SocketShutdown.Both);
IPsocket.Close();
#endregion
#region 将中转请求收到的数据发回客户端
clientSocket.Send(recvBytes, 0 , count, 0 );
Write( " 正在返回数据... " + count);
#endregion
#region 结束请求,关闭客户端Socket
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
recvBytes = null ;
Write( " 完成,已关闭连接... " );
Write( " -----------------------------请求结束--------------------------- " );
#endregion
}
catch (Exception err)
{
System.Console.WriteLine(err.Message + err.Source);
}
}
// 从请求头里解析出url和端口号
private string GetUrl( string clientmessage, int port)
{
int index1 = clientmessage.IndexOf( ' ' );
int index2 = clientmessage.IndexOf( ' ' , index1 + 1 );
if ((index1 == - 1 ) || (index2 == - 1 ))
{
throw new IOException();
}
string part1 = clientmessage.Substring(index1 + 1 , index2 - index1).Trim();
string url = string .Empty;
if ( ! part1.Contains( " http:// " ))
{
part1 = " http:// " + part1;
}
Uri uri = new Uri(part1);
url = uri.Host;
port = uri.Port;
return url;
}
// 接收客户端的HTTP请求数据
private int ReadMessage( byte [] readByte, ref Socket s, ref string clientmessage)
{
int bytes = s.Receive(readByte, readByte.Length, 0 );
clientmessage = Encoding.ASCII.GetString(readByte);
return bytes;
}
private void Write( string msg)
{
// return;
System.Console.WriteLine(msg);
}
}
}
namespace TCPProxy
{
public class Proxy
{
Socket clientSocket; // 接收和返回
Byte[] read = null ; // 存储来自客户端请求数据包
Byte[] recvBytes = null ; // 存储中转请求返回的数据
public Proxy(Socket socket)
{
clientSocket = socket;
recvBytes = new Byte[ 1024 * 1024 ];
clientSocket.ReceiveBufferSize = recvBytes.Length;
clientSocket.SendBufferSize = recvBytes.Length;
clientSocket.SendTimeout = 10000 ;
clientSocket.ReceiveTimeout = 10000 ;
}
public void Run()
{
#region 获取客户端请求数据
string clientmessage = "" ;
read = new byte [clientSocket.Available];
int bytes = ReadMessage(read, ref clientSocket, ref clientmessage);
if (bytes == 0 )
{
Write( " 读取不到数据! " );
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
return ;
}
int port = 80 ;
string url = GetUrl(clientmessage, port);
#endregion
try
{
#region IP解析获取
IPHostEntry IPHost = Dns.GetHostEntry(url);
Write( " -----------------------------请求开始--------------------------- " );
Write( " http:// " + IPHost.HostName);
string [] aliases = IPHost.Aliases;
IPAddress[] address = IPHost.AddressList; // 解析出要访问的服务器地址
Write( " IP地址: " + address[ 0 ]);
#endregion
#region 创建中转Socket及建立连接
IPEndPoint ipEndpoint = new IPEndPoint(address[ 0 ], port);
Socket IPsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 创建连接Web服务器端的Socket对象
IPsocket.Connect(ipEndpoint);
// Socket连Web接服务器
if (IPsocket.Connected)
{
Write( " Socket 正确连接! " );
}
#endregion
#region 发送中转请求
IPsocket.Send(read, 0 );
Write( " 发送字节: " + read.Length);
#endregion
#region 接收中转请求数据
int length = 0 , count = 0 ;
do
{
length = IPsocket.Receive(recvBytes, count, IPsocket.Available, 0 );
count = count + length;
Write( " 正在接收数据... " + length);
System.Threading.Thread.Sleep( 100 ); // 关键点,请求太快数据接收不全
}
while (IPsocket.Available > 0 );
#endregion
#region 关闭中转请求Socket
IPsocket.Shutdown(SocketShutdown.Both);
IPsocket.Close();
#endregion
#region 将中转请求收到的数据发回客户端
clientSocket.Send(recvBytes, 0 , count, 0 );
Write( " 正在返回数据... " + count);
#endregion
#region 结束请求,关闭客户端Socket
clientSocket.Shutdown(SocketShutdown.Both);
clientSocket.Close();
recvBytes = null ;
Write( " 完成,已关闭连接... " );
Write( " -----------------------------请求结束--------------------------- " );
#endregion
}
catch (Exception err)
{
System.Console.WriteLine(err.Message + err.Source);
}
}
// 从请求头里解析出url和端口号
private string GetUrl( string clientmessage, int port)
{
int index1 = clientmessage.IndexOf( ' ' );
int index2 = clientmessage.IndexOf( ' ' , index1 + 1 );
if ((index1 == - 1 ) || (index2 == - 1 ))
{
throw new IOException();
}
string part1 = clientmessage.Substring(index1 + 1 , index2 - index1).Trim();
string url = string .Empty;
if ( ! part1.Contains( " http:// " ))
{
part1 = " http:// " + part1;
}
Uri uri = new Uri(part1);
url = uri.Host;
port = uri.Port;
return url;
}
// 接收客户端的HTTP请求数据
private int ReadMessage( byte [] readByte, ref Socket s, ref string clientmessage)
{
int bytes = s.Receive(readByte, readByte.Length, 0 );
clientmessage = Encoding.ASCII.GetString(readByte);
return bytes;
}
private void Write( string msg)
{
// return;
System.Console.WriteLine(msg);
}
}
}
在控制台里调用:
代码
using
System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Net.Sockets;
using System.Threading;
namespace TCPProxy
{
class Program
{
static void Main( string [] args)
{
Listen( 8989 );
}
static void Write( string msg)
{
Console.WriteLine(msg);
}
static void Listen( int port)
{
Write( " 准备监听端口: " + port);
TcpListener tcplistener = new TcpListener(port);
try
{
tcplistener.Start();
}
catch
{
Write( " 该端口已被占用,请更换端口号!!! " );
ReListen(tcplistener);
}
Write( " 确认:y/n (yes or no): " );
string isOK = Console.ReadLine();
if (isOK == " y " )
{
Write( " 成功监听端口: " + port);
// 侦听端口号
Socket socket;
while ( true )
{
socket = tcplistener.AcceptSocket();
// 并获取传送和接收数据的Scoket实例
Proxy proxy = new Proxy(socket);
// Proxy类实例化
Thread thread = new Thread( new ThreadStart(proxy.Run));
// 创建线程
thread.Start();
System.Threading.Thread.Sleep( 10 );
// 启动线程
}
}
else
{
ReListen(tcplistener);
}
}
static void ReListen(TcpListener listener)
{
if (listener != null )
{
listener.Stop();
listener = null ;
}
Write( " 请输入监听端口号: " );
string newPort = Console.ReadLine();
int port;
if ( int .TryParse(newPort, out port))
{
Listen(port);
}
else
{
ReListen(listener);
}
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Net.Sockets;
using System.Threading;
namespace TCPProxy
{
class Program
{
static void Main( string [] args)
{
Listen( 8989 );
}
static void Write( string msg)
{
Console.WriteLine(msg);
}
static void Listen( int port)
{
Write( " 准备监听端口: " + port);
TcpListener tcplistener = new TcpListener(port);
try
{
tcplistener.Start();
}
catch
{
Write( " 该端口已被占用,请更换端口号!!! " );
ReListen(tcplistener);
}
Write( " 确认:y/n (yes or no): " );
string isOK = Console.ReadLine();
if (isOK == " y " )
{
Write( " 成功监听端口: " + port);
// 侦听端口号
Socket socket;
while ( true )
{
socket = tcplistener.AcceptSocket();
// 并获取传送和接收数据的Scoket实例
Proxy proxy = new Proxy(socket);
// Proxy类实例化
Thread thread = new Thread( new ThreadStart(proxy.Run));
// 创建线程
thread.Start();
System.Threading.Thread.Sleep( 10 );
// 启动线程
}
}
else
{
ReListen(tcplistener);
}
}
static void ReListen(TcpListener listener)
{
if (listener != null )
{
listener.Stop();
listener = null ;
}
Write( " 请输入监听端口号: " );
string newPort = Console.ReadLine();
int port;
if ( int .TryParse(newPort, out port))
{
Listen(port);
}
else
{
ReListen(listener);
}
}
}
}
本人测试:
在打开IE-》工具->Internet选项->链接->局域网设置->代理连接-》输入IP和端口号
访问网站,查看控制台输出消息,页面访问正常,测试通过。
本来想测试下QQ代理,无奈本地已被封,服务器也没端口可用。有空回家再测了。
提供代码下载