我们知道编程的时候使用代理服务器并不是一件爽心悦目的事情,可是很多时候又是迫不得已的。微软在.NET Framework得System.Net名称空间里给我们提供了一个WebProxy类,不过这是一个http代理,这种代理使用起来受限太多,很不方便。如果我们需要访问更多的网络服务,socks代理是一个理想的选择。下面是C#编写的一个匿名socks5代理使用示例:
#region 连接匿名socks5服务器代码
private bool ConnectProxyServer(string strRemoteHost, int iRemotePort, Socket sProxyServer)
{
//构造Socks5代理服务器第一连接头(无用户名密码)
byte[] bySock5Send = new Byte[10];
bySock5Send[0] = 5;
bySock5Send[1] = 1;
bySock5Send[2] = 0;
//发送Socks5代理第一次连接信息
sProxyServer.Send(bySock5Send, 3, SocketFlags.None);
byte[] bySock5Receive = new byte[10];
int iRecCount = sProxyServer.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None);
if ( iRecCount<2 )
{
sProxyServer.Close();
throw new Exception("不能获得代理服务器正确响应。");
}
if ( bySock5Receive[0]!=5 || ( bySock5Receive[1]!=0 && bySock5Receive[1]!=2 ) )
{
sProxyServer.Close();
throw new Exception("代理服务其返回的响应错误。");
}
if ( bySock5Receive[1]==0 )
{
bySock5Send[0] = 5;
bySock5Send[1] = 1;
bySock5Send[2] = 0;
bySock5Send[3] = 1;
IPAddress ipAdd = Dns.Resolve(strRemoteHost).AddressList[0];
string strIp = ipAdd.ToString();
string []strAryTemp = strIp.Split(new char[] {'.'});
bySock5Send[4] = Convert.ToByte(strAryTemp[0]);
bySock5Send[5] = Convert.ToByte(strAryTemp[1]);
bySock5Send[6] = Convert.ToByte(strAryTemp[2]);
bySock5Send[7] = Convert.ToByte(strAryTemp[3]);
bySock5Send[8] = (byte)(iRemotePort/256);
bySock5Send[9] = (byte)(iRemotePort%256);
sProxyServer.Send(bySock5Send, bySock5Send.Length, SocketFlags.None);
iRecCount = sProxyServer.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None);
if ( bySock5Receive[0]!=5 || bySock5Receive[1]!=0 )
{
sProxyServer.Close();
throw new Exception("第二次连接Socks5代理返回数据出错。");
}
return true ;
}
else
{
if ( bySock5Receive[1]==2 )
throw new Exception("代理服务器需要进行身份确认。");
else return false ;
}
}
#endregion
private bool ConnectProxyServer(string strRemoteHost, int iRemotePort, Socket sProxyServer)
{
//构造Socks5代理服务器第一连接头(无用户名密码)
byte[] bySock5Send = new Byte[10];
bySock5Send[0] = 5;
bySock5Send[1] = 1;
bySock5Send[2] = 0;
//发送Socks5代理第一次连接信息
sProxyServer.Send(bySock5Send, 3, SocketFlags.None);
byte[] bySock5Receive = new byte[10];
int iRecCount = sProxyServer.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None);
if ( iRecCount<2 )
{
sProxyServer.Close();
throw new Exception("不能获得代理服务器正确响应。");
}
if ( bySock5Receive[0]!=5 || ( bySock5Receive[1]!=0 && bySock5Receive[1]!=2 ) )
{
sProxyServer.Close();
throw new Exception("代理服务其返回的响应错误。");
}
if ( bySock5Receive[1]==0 )
{
bySock5Send[0] = 5;
bySock5Send[1] = 1;
bySock5Send[2] = 0;
bySock5Send[3] = 1;
IPAddress ipAdd = Dns.Resolve(strRemoteHost).AddressList[0];
string strIp = ipAdd.ToString();
string []strAryTemp = strIp.Split(new char[] {'.'});
bySock5Send[4] = Convert.ToByte(strAryTemp[0]);
bySock5Send[5] = Convert.ToByte(strAryTemp[1]);
bySock5Send[6] = Convert.ToByte(strAryTemp[2]);
bySock5Send[7] = Convert.ToByte(strAryTemp[3]);
bySock5Send[8] = (byte)(iRemotePort/256);
bySock5Send[9] = (byte)(iRemotePort%256);
sProxyServer.Send(bySock5Send, bySock5Send.Length, SocketFlags.None);
iRecCount = sProxyServer.Receive(bySock5Receive, bySock5Receive.Length, SocketFlags.None);
if ( bySock5Receive[0]!=5 || bySock5Receive[1]!=0 )
{
sProxyServer.Close();
throw new Exception("第二次连接Socks5代理返回数据出错。");
}
return true ;
}
else
{
if ( bySock5Receive[1]==2 )
throw new Exception("代理服务器需要进行身份确认。");
else return false ;
}
}
#endregion
关于socks5代理的详细文档,可以参看RFC 1928。
使用上面的代码需要有一个匿名的socks5代理服务器,然后调用:
private Socket GetSocket(
string strIpAdd,
int iPort)
{
IPAddress hostadd = Dns.Resolve(strIpAdd).AddressList[0];
IPEndPoint EPhost = new IPEndPoint(hostadd, iPort);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Connect(EPhost);
return s ;
}
sRemoteHost = GetSocket(proxyHost, proxyProt);
ConnectProxyServer("61.135.134.24", 80 , sRemoteHost);
{
IPAddress hostadd = Dns.Resolve(strIpAdd).AddressList[0];
IPEndPoint EPhost = new IPEndPoint(hostadd, iPort);
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Connect(EPhost);
return s ;
}
sRemoteHost = GetSocket(proxyHost, proxyProt);
ConnectProxyServer("61.135.134.24", 80 , sRemoteHost);
如果您需要使用非匿名的socks5代理,把RFC 1928后面关于用户验证的部分实现就可以了,由于我使用的都是匿名的socks5代理,所以没有做这个部分得工作。