// методы работы с исходящим подключением /// <summary> /// Запускает процесс поиска маршрута /// </summary> /// <param name="target">Целевой компьютер</param> /// <param name="mat">Ид раздачи</param> /// <returns>Сокет, подключенный к следующему компьютеру в цепочке, либо null, если маршрут не удалось установить</returns> public Socket Connect(Client target, int mat) { foreach (Material m in ProgramMaterials.MaterialsArray) { foreach (Connection c in m.Connections) { try { IPAddress ip = ((IPEndPoint)c.Socket.RemoteEndPoint).Address; short port = 30095; Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); try { sock.Connect(ip, port); } catch (Exception) { continue; } NetworkStream comStr = new NetworkStream(sock); comStr.WriteByte((byte)IDT_Protocol.Connect); int resp = comStr.ReadByte(); if(resp != (int)IDT_Protocol.Connected) { TerminateConnection(comStr); continue; } byte[] temp = target.Serialize(); comStr.WriteByte((byte)IDT_Protocol.IsLink); comStr.Write(temp, 0, 6); resp = comStr.ReadByte(); if(resp != (int)IDT_Protocol.LinkAccesible) { TerminateConnection(comStr); continue; } comStr.WriteByte((byte)IDT_Protocol.IsMaterial); comStr.Write(bc.GetBytes(mat), 0, 4); IDT_Protocol res = (IDT_Protocol)comStr.ReadByte(); if(res == IDT_Protocol.MaterialNotFound) comStr.WriteByte((byte)IDT_Protocol.TerminateTransaction); return sock; } catch (Exception) { continue; } } } return null; }
/// <summary> /// Пытается произвести рекурсивное подключение от компьютера к компьютеру, пока не установит цепочку связей до конечного компьютера /// </summary> /// <param name="con">Предыдущий компьютер в сети</param> /// <param name="targetHost">Целевой компьютер</param> /// <param name="mat">Ид раздачи</param> /// <returns>Сокет, подключенный к следующему компьютеру в цепочке, либо null, если маршрут не удалось установить</returns> Socket TryConnect(Connection con, out Client targetHost, int mat) { NetworkStream nStream = new NetworkStream(con.Socket); byte[] buf = new byte[6]; nStream.Read(buf, 0, 6); targetHost = new Client(); targetHost.Deserialize(buf); foreach (Client c in targets) { if (c == targetHost) { nStream.WriteByte((byte)(IDT_Protocol.TerminateTransaction)); return null; } } Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); try { sock.Connect(targetHost.ip, targetHost.port); sock.Send(new byte[] { (byte)C_C_Protocol.Connect}); byte[] receive = new byte[2]; sock.Receive(receive, 0, 1, SocketFlags.None); sock.Receive(receive, 1, 1, SocketFlags.None); if((C_C_Protocol) receive[0] != C_C_Protocol.Connected || receive[1] ==0) { sock.Close(); throw new SocketException(); } sock.Send(new byte[] {(byte)C_C_Protocol.IsMaterial}); byte[] temp = bc.GetBytes(mat); sock.Send(temp); sock.Receive(temp, 1, SocketFlags.None); if (temp[0] != (byte)C_C_Protocol.MaterialResponse) { sock.Close(); throw new SocketException(); } return sock; } catch (SocketException) { foreach (Material m in ProgramMaterials.MaterialsArray) { foreach (Connection c in m.Connections) { IPAddress ip = ((IPEndPoint)c.Socket.RemoteEndPoint).Address; short port = (short)((IPEndPoint)c.Socket.RemoteEndPoint).Port; try { sock.Connect(ip, port); } catch (Exception) { continue; } return Connect(targetHost, mat); } } return null; } }
/// <summary> /// Процедура, содержащая цикл обработки команд протокола IDT /// </summary> /// <param name="con">Объект подключения с инициатором сеанса</param> private void IDTSession(object con) { Connection c = (Connection)con; NetworkStream nStream = new NetworkStream(c.Socket); /*общие данные*/ Socket sock = null; int material = 0; Client targetHost = new Client() ; IDT_Protocol com = (IDT_Protocol)nStream.ReadByte(); nStream.Close(); switch (com) { case IDT_Protocol.IsLink: targets.Add(targetHost); sock = TryConnect(c, out targetHost, material); break; case IDT_Protocol.IsMaterial: material = CheckMaterial(c,sock, targetHost); break; case IDT_Protocol.GetPart: RequestPart(c, sock, material, targetHost); break; case IDT_Protocol.TerminateTransaction: targets.Remove(targetHost); break; } }
/// <summary> /// Метод запрашивает часть данных у подключенного IDT сервиса, либо конечного компьютера и отправляет ее инициатору подключения - /// другому IDT сервису, либо первому компьютеру в цепочке /// </summary> /// <param name="c">Объект подключения с инициатором</param> /// <param name="sock">Сокет, подключенный к следующему компьютеру в цепочке</param> /// <param name="material">Идентификатор раздачи</param> /// <param name="targetHost">Целевой компьютер, для достижения которого строилась цепочка</param> private void RequestPart(Connection c, Socket sock, int material, Client targetHost) { NetworkStream nStream = new NetworkStream(sock); NetworkStream ansStream = new NetworkStream(c.Socket); byte[] bcom = new byte[] { (byte)C_C_Protocol.GetPart }; byte[] bmat = bc.GetBytes(material); byte[] bfile = new byte[4]; byte[] bpart = new byte[4]; byte[] bsize = new byte[4]; ansStream.Read(bfile, 0, 4); ansStream.Read(bpart, 0, 4); ansStream.Read(bsize, 0, 4); int size = bc.ToInt32(bsize, 0); // Работа в режиме целевого компьютера if (IsTarget(sock, targetHost)) { nStream.Write(bcom, 0, 1); nStream.Write(bmat, 0, 1); nStream.Write(bfile, 0, 4); nStream.Write(bpart, 0, 4); C_C_Protocol resp = (C_C_Protocol)nStream.ReadByte(); int ispart = nStream.ReadByte(); if (resp != C_C_Protocol.SendPart || ispart == 0) { ansStream.WriteByte((byte)IDT_Protocol.SendPart); ansStream.WriteByte(0); return; } nStream.Read(new byte[12], 0, 12); byte[] buffer = new byte[size]; for (int i = 0; i != size; ) { i += nStream.Read(buffer, i, size - i); } ansStream.WriteByte((byte)IDT_Protocol.SendPart); ansStream.WriteByte(0); ansStream.Write(buffer, 0, size); } else//работа в режиме промежуточной ячейки сети { IDT_Protocol resp = (IDT_Protocol) nStream.ReadByte(); int status = nStream.ReadByte(); if (resp != IDT_Protocol.SendPart) return; if (status == 0) { ansStream.WriteByte((byte)IDT_Protocol.SendPart); ansStream.WriteByte((byte)status); return; } byte[] buffer = new byte[size]; for (int i = 0; i != size; ) { i += nStream.Read(buffer, i, size - i); } ansStream.WriteByte((byte)IDT_Protocol.SendPart); ansStream.WriteByte((byte)status); ansStream.Write(buffer, 0, size); } }
/// <summary> /// Проверяет наличие раздачи на конечном компютере, команда передается по цепочке /// </summary> /// <param name="c">Объект подключения с инициатором</param> /// <param name="sock">Сокет, подключенный к следующему компьютеру в цепочке</param> /// <param name="targetHost">Целевой компьютер, для достижения которого строилась цепочка</param> /// <returns>Возвращает номер раздачи, полученный от предыдущего компьютера в цепи</returns> private int CheckMaterial(Connection con, Socket sock, Client targetHost) { NetworkStream nStream = new NetworkStream(sock); NetworkStream ansStream = new NetworkStream(con.Socket); byte[] temp = new byte[4]; ansStream.Read(temp, 0, 4); int material = bc.ToInt32(temp,0); if (IsTarget(sock, targetHost)) // работа в режиме целевого хоста { nStream.Write(new byte[] {(byte)C_C_Protocol.IsMaterial},0,1); nStream.Write(temp, 0, 4); byte[] resp = new byte[6]; nStream.Read(resp,0,6); if (resp[5] == 1) { ansStream.Write(new byte[] { (byte)IDT_Protocol.MaterialConfirmed }, 0, 1); return material; } else { ansStream.Write(new byte[] { (byte)IDT_Protocol.MaterialNotFound }, 0, 1); return 0; } } else // работа в режиме ячейки { nStream.Write(new byte[] { (byte)C_C_Protocol.IsMaterial }, 0, 1); IDT_Protocol resp = (IDT_Protocol)nStream.ReadByte(); if (resp == IDT_Protocol.MaterialNotFound) return 0; else return material; } }
/// <summary> /// Сравнивает IP и порт следующего компьютера в цепочке. /// </summary> /// <param name="sock">Сокет следующего компьютера в сети</param> /// <param name="targetHost">Целевой компьютер</param> /// <returns>True, если следующий компьютер в цепи - конечный</returns> private static bool IsTarget(Socket sock, Client targetHost) { IPAddress ip = ((IPEndPoint)sock.RemoteEndPoint).Address; if (targetHost.ip == ip) return true; return false; }
/// <summary> /// Конструктор, вызывается при добавлении раздачи из существующего метафайла /// </summary> /// <param name="PathToMetaFile">Путь к метафайлу</param> public Material(string dir, string PathToMetaFile) { ProgramMaterials.cur_file = 0; BinaryFormatter bf = new BinaryFormatter(); if (!System.IO.File.Exists(PathToMetaFile)) throw new Exceptions.IsNotMetafile(); FileStream metafile = new FileStream(PathToMetaFile, FileMode.Open); if (dir[dir.Length - 1] != '\\') dir += "\\"; try { Meta_File mf = (Meta_File)bf.Deserialize(metafile); IdClient = mf.ID_Client; IdMaterial = mf.ID_matirial; Name = mf.name; server = mf.IP_Port_Server; Files = new File[mf.files.Length]; for (int i = 0; i < mf.files.Length; i++) { ProgramMaterials.cur_file = i; Files[i] = new File(mf.files[i].path, dir + mf.files[i].path, mf.files[i].File_Size, mf.files[i].Count_Parts_, mf.files[i].Hashs, mf.files[i].Part_size); } filese_that_need_to_download = new int[Files.Length]; cread_map_download(); } catch (System.Runtime.Serialization.SerializationException) { throw new Exceptions.WrongMetafileFormat(); } finally { metafile.Close(); } SetSize(); SetStatus(); }
private void ReadClients(string filename) { FileStream fs = new FileStream(filename, FileMode.Open); Read: while (fs.Length > fs.Position) { byte[] temp = new byte[6]; fs.Read(temp, 0, 6); Client t = new Client(); t.Deserialize(temp); IPAddress IP_Client = t.ip; short Port_Client = t.port; IPEndPoint ip; for (int i = 0; i < connections.Count; i++) { ip = (IPEndPoint)(connections[i].Socket.RemoteEndPoint); if (ip.Address.ToString() == IP_Client.ToString()) goto Read; } Socket socket_download = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); try { Connection con = new Connection(); con.Thread = new Thread(Download); con.Thread.IsBackground = true; con.Socket = socket_download; con.Thread.Start(con); socket_download.Connect(new IPEndPoint(IP_Client, Port_Client)); } catch (SocketException) { /*if (Config.IDT_Enaibled) { Client cl = new Client(IP_Client, Port_Client); System.Threading.Thread th = new Thread(IDT_client); th.Start(cl); }*/ } } fs.Close(); }
/// <summary> /// Выдает таблицу клиентов /// </summary> /// <param name="nStream">Открытый сетевой поток</param> private void GetClientsTable(NetworkStream nStream) { byte[] temp = new byte[4]; nStream.Read(temp, 0, 4); int IdMaterial = bc.ToInt32(temp, 0); nStream.WriteByte((byte)CTE_Protocol.ReceiveClientsTable); foreach (Material m in ProgramMaterials.MaterialsArray) { if (m.IdMaterial == IdMaterial) { int number = m.Connections.Count; temp = bc.GetBytes(number); for (int i = 0; i < number; i++) { IPEndPoint ip = (IPEndPoint) m.Connections[i].Socket.RemoteEndPoint; Client cl = new Client(ip.Address, (short)ip.Port); temp = cl.Serialize(); nStream.Write(temp, 0, 6); } } } }