我正在做一个完全基于Tor网络的p2p应用程序。该应用程序使用2个端口进行通信,例如8001用于控制命令,7001用于聊天通道。该对等方首先连接到8001以请求聊天,并且当我(另一个对等方)接受他的请求时,我尝试在7001上与他连接(他应在监听并等待我这样做)。我这样做是为了进行身份验证。
总之,一个对等方侦听2个端口,一个侦听端口用于控制(8001),根据他的侧面(聊天请求发送方/接收方),他侦听7001(聊天)。协商如下(假定控制通道建立在8001上) -Me将 CHATREQ 发送给对等方,然后侦听7001 -Peer向我发送 CHATOK ,并尝试连接到我的7001
我无法理解的问题是,在大多数情况下,与8001的连接无法连接,尽管与8001的连接运行良好!什么可以使一个端口上的连接正常而另一端失败?有什么我误会的东西吗?或这是该机制本身的问题(请避免不修改整个应用程序以使其绕过它!因此,无法更改在2个单独的端口上工作:))
以下是相关的代码部分
1- Socks5连接功能
public static Socket ConnectViaSocks(ushort Socksport, string RemoteAddress, ushort RemotePort, ref sbyte result)
{
Socket torsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
torsock.Connect("127.0.0.1", Socksport);
// Sending intial request : Authentication
byte[] AuthReq = { 0x05, 0x01, 0x00 };
torsock.Send(AuthReq);
// Getting reply
byte[] buffer = new byte[2];
int received = torsock.Receive(buffer);
if (buffer[1] != 0x00) { torsock.Close(); throw new MyException("SOCKS5 : Authentication error "); }
// Sending Connect request to a domain (.onion domain)
byte[] header = { 0x05, 0x01, 0x00, 0x03 };
byte DomainLength =(byte) RemoteAddress.Length;
byte[] DomainName = Encoding.ASCII.GetBytes(RemoteAddress);
byte[] ConnRequest = new byte[4+1+DomainLength+2]; //Request format = {0x05 0x01 0x00 0x03 Domainlength(1 byte) DomainNmame(Variable Bytes) portNo(2 bytes) }
System.Buffer.BlockCopy(header , 0, ConnRequest, 0, header.Length);
ConnRequest[header.Length] = DomainLength;
System.Buffer.BlockCopy(DomainName, 0, ConnRequest, header.Length+1, DomainName.Length);
ConnRequest[header.Length + 1 + DomainName.Length ] = (byte)(RemotePort>>8);
ConnRequest[header.Length + 1 + DomainName.Length + 1] = (byte)(RemotePort & 255);
torsock.Send(ConnRequest);
byte[] buffer2 = new byte[10];
received = torsock.Receive(buffer2);
if (buffer2[1] != 0x00) { torsock.Close(); }
result = (sbyte)buffer2[1];
return torsock;
}
2-通过我拥有的私钥建立隐藏服务(又称临时隐藏服务)命令。
string command = "ADD_ONION RSA1024:" + PrivateKey + " Port=7001 Port=8001"; // Creating Onion hidden service on ports 7001,8001
torctrl.sendCommand(command);
注意:torctrl是套接字周围的包装,它将命令字符串发送到tor控制端口。
3-建立聊天频道:
3.1:发起方对等发送聊天请求:
NB。 Globals.SKEY =不带.onion的洋葱地址,
SockThreads.SockTxThread =将(contactSocket)上的(消息)发送给对等方的线程
cmd.StrCmd =将聊天请求格式化为整个应用程序中的统一消息格式
Console.WriteLine("[Notice] Sending chat request to " + onion);
message = cmd.StrCmd(Globals.SKEY, Globals.nickname, "CHATREQ", 0, "");
Socket contactSocket = Globals.OnionSocks[onion];
Thread myNewThreadTx = new Thread(() => SockThreads.SockTxThread(contactSocket, message));
myNewThreadTx.Start();
3.2响应CHAT REQ
NB:MsgOnion:对方的地址向我发送了聊天请求
Console.ForegroundColor = System.ConsoleColor.DarkRed;
Console.WriteLine("[Notice] Starting Chat channel creation");
ToPeerMsg = cmd.StrCmd(Globals.SKEY, Globals.nickname, "CHATOK", 0, "");
Thread myNewThreadTx = new Thread(() => SockThreads.SockTxThread(sock, ToPeerMsg));
myNewThreadTx.Start();
Thread.Sleep(1000);
// Connecting to chat port of incoming user
Socket Chatsock = SocketSocks.ConnectViaSocks(9150, MsgOnion + ".onion", 7001, ref result);
if (result == 0)
{ /* Some code to Rx/Tx messages,if come here no problem at all :)*/}
3.3:响应“聊天正常”
Thread ChatListenThread = new Thread(() =>SockThreads.SockChatListener());
ChatListenThread.Start();
ChatListenThread:线程在7001上侦听,如果建立连接,则聊天的重要工作(打开线程,控件等)。相关问题:
#region Create listener and accept sockets
TcpListener CtrlListener = new TcpListener(System.Net.IPAddress.Any, 7001);
CtrlListener.Start();
#endregion
#region Wait for a connection
Socket sock;
sock = CtrlListener.AcceptSocket();
Console.WriteLine("[Notice] Chat channel established with peer .... Congrats =) ");