Консультация № 191545
26.10.2017, 12:49
0.00 руб.
0 8 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос:

Предполагая, что в некотором каталоге на диске сохранено большое
количество файлов с логами (журналами работы) прокси-сервера,
написать программу вычисляющую статистику потребления
трафика сети Интернет. На выходе программа должна создавать три
текстовых документа: статистика по пользователям, статистика по
доменам, статистика по датам. В качестве статистики использовать
общий объем потребленного трафика, соответственно
пользователем за все дни, при обращении к домену, в указанный
день.
При разработке программы считать, что каждый файл должен
обрабатываться отдельно параллельно выполняющимся участком
кода. После обработки всех файлов, полученные результаты для
каждого из них должны суммироваться в общую сводку.

Можете написать что мы и где делаем? комментарии

Код:

class Program
{
static void Main(string[] args)
{
LogFileGenerator gen = new LogFileGenerator();
gen.GenerateAndSave("D:\\logs", new DateTime(2017, 9, 13), new DateTime(2017, 9, 14));
LogStatistics logstat= new LogStatistics("D:\\logs");
logstat.UserStatistics();
logstat.DomainStatistics();
logstat.DateStatistics();

logstat.SaveUserStatReport("D:\\logs\\user_report.txt");
logstat.SaveDomainStatReport("D:\\logs\\domain_report.txt");
logstat.SaveDateStatReport("D:\\logs\\date_report.txt");

Console.ReadKey(true);
}
}

[Serializable]
class LogItem
{
public DateTime date;
public int userIP;
public int domainIP;
public string domainName = "";
public ulong trafficSize;

public LogItem() { }

public LogItem(DateTime date, int userIP, int domainIP, string domainName, ulong trafficSize)
{
this.date = date;
this.userIP = userIP;
this.domainIP = domainIP;
this.trafficSize = trafficSize;
this.domainName = domainName;
}
}

class LogFileGenerator
{
List<string> letters = new List<string>(){"a","b", "c","d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s","t", "u", "v", "w", "x", "y", "z" };
List<string> domains = new List<string>() { ".com", ".ru", ".su" };
public void GenerateAndSave(string pathToSave, DateTime startDate, DateTime endDate)
{
Random rand = new Random();
List<List<LogItem>> logPackage = new List<List<LogItem>>();
int max = endDate.Day - startDate.Day;
for (int i = 0; i <= max; i++)
{
List<LogItem> list = new List<LogItem>();
for (int k = 0; k < rand.Next(2, 5); k++)
{
string domainname = "";
for (int j = 0; j < rand.Next(4, 10); j++)
{
domainname += letters[rand.Next(0, letters.Count - 1)];
}
domainname += domains[rand.Next(0, domains.Count - 1)];
list.Add(new LogItem(startDate.AddDays(i), rand.Next(12345, 12350), rand.Next(45678, 45680), domainname, (ulong)rand.Next(1, 10)));
}

using (Stream st = new FileStream(pathToSave+"\"+startDate.AddDays(i).ToShortDateString()+ ".log", FileMode.Create))
{
IFormatter f = new BinaryFormatter();
f.Serialize(st, list);
}

foreach(var l in list)
{
List<string> IP = new List<string>();
int mask = 255;
for (int j = 0; j < 4; j++)
{
IP.Add(((l.userIP >> j * 8) & mask).ToString());
}
IP.Reverse();
string uip = String.Join(".", IP);

IP.Clear();
for (int j = 0; j < 4; j++)
{
IP.Add(((l.domainIP >> j * 8) & mask).ToString());
}
IP.Reverse();
string dip = String.Join(".", IP);
Console.WriteLine(l.date.ToShortDateString() +" " + uip + " " + dip + " " + l.trafficSize);
}
}
}
}

class LogStatistics
{
private List<Dictionary<int, ulong>> user = new List<Dictionary<int, ulong>>();
private List<Dictionary<int, ulong>> domain = new List<Dictionary<int, ulong>>();
private List<Dictionary<DateTime, ulong>> date= new List<Dictionary<DateTime, ulong>>();

public Dictionary<int, ulong> user_stat;
public Dictionary<int, ulong> domain_stat;
public Dictionary<DateTime, ulong> date_stat;
List<string> logFiles;


public LogStatistics(string logDir)
{
user_stat = new Dictionary<int, ulong>();
domain_stat = new Dictionary<int, ulong>();
date_stat = new Dictionary<DateTime, ulong>();
logFiles = new List<string>();
logFiles = System.IO.Directory.GetFiles(logDir,"*.log").ToList();
}

public void UserStatistics()
{
var events = new List<ManualResetEvent>();

ThreadPool.SetMaxThreads(4, 4);

foreach(var file in logFiles)
{
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(arg =>
{
UserStatisticsWorker(file);
resetEvent.Set();
});
events.Add(resetEvent);
}
WaitHandle.WaitAll(events.ToArray());
Console.WriteLine("User stat done");

foreach (var piece in user)
{
foreach (var item in piece)
{
if (user_stat.ContainsKey(item.Key))
{
user_stat[item.Key] += item.Value;
}
else
{
user_stat.Add(item.Key, item.Value);
}
}
}
}

public void DomainStatistics()
{
var events = new List<ManualResetEvent>();

ThreadPool.SetMaxThreads(4, 4);
ThreadPool.SetMinThreads(4, 4);
foreach (var file in logFiles)
{
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(arg =>
{
DomainStatisticsWorker(file);
resetEvent.Set();
});
events.Add(resetEvent);
}
WaitHandle.WaitAll(events.ToArray());
Console.WriteLine("Domain stat done");

foreach (var piece in domain)
{
foreach (var item in piece)
{
if (domain_stat.ContainsKey(item.Key))
{
domain_stat[item.Key] += item.Value;
}
else
{
domain_stat.Add(item.Key, item.Value);
}
}
}
}

public void DateStatistics()
{
var events = new List<ManualResetEvent>();

ThreadPool.SetMaxThreads(4, 4);
foreach(var file in logFiles)
{
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(arg =>
{
DateStatisticsWorker(file);
resetEvent.Set();
});
events.Add(resetEvent);
}
WaitHandle.WaitAll(events.ToArray());
Console.WriteLine("Date stat done");

foreach (var piece in date)
{
foreach (var item in piece)
{
if (date_stat.ContainsKey(item.Key))
{
date_stat[item.Key] += item.Value;
}
else
{
date_stat.Add(item.Key, item.Value);
}
}
}
}

public void SaveUserStatReport(string dirPath)
{
string output = "";
foreach (var item in user_stat)
{
List<string> IP = new List<string>();
int mask = 255;
for (int i = 0; i < 4; i++)
{
IP.Add(((item.Key >> i*8) & mask).ToString());
}
IP.Reverse();
output += String.Join(".",IP);
output += ": " + item.Value + "byte\r\n";
}
File.WriteAllText(dirPath, output);
}

public void SaveDomainStatReport(string dirPath)
{
string output = "";
foreach (var item in domain_stat)
{
List<string> IP = new List<string>();
int mask = 255;
for (int i = 0; i < 4; i++)
{
IP.Add(((item.Key >> i * 8) & mask).ToString());
}
IP.Reverse();
output += String.Join(".", IP);
output += ": " + item.Value + "byte\r\n";
}
File.WriteAllText(dirPath, output);
}

public void SaveDateStatReport(string dirPath)
{
string output = "";
foreach (var item in date_stat)
{
output += item.Key.ToShortDateString()+": " + item.Value + "byte\r\n";
}
File.WriteAllText(dirPath, output);
}

private void UserStatisticsWorker(object state)
{
Console.WriteLine("user");
List<LogItem> log = new List<LogItem>();
string logPath = (string)state;
using (Stream st = new FileStream(logPath, FileMode.Open, FileAccess.Read))
{
IFormatter f = new BinaryFormatter();
log = (List<LogItem>)f.Deserialize(st);
}

Dictionary<int, ulong> stat = new Dictionary<int, ulong>();

foreach (var item in log)
{
if(stat.ContainsKey(item.userIP))
{
stat[item.userIP] += item.trafficSize;
}
else
{
stat.Add(item.userIP, item.trafficSize);
}
}
user.Add(stat);
}

private void DomainStatisticsWorker(object state)
{
Console.WriteLine("domain");
List<LogItem> log = new List<LogItem>();
string logPath = (string)state;
using (Stream st = new FileStream(logPath, FileMode.Open, FileAccess.Read))
{
IFormatter f = new BinaryFormatter();
log = (List<LogItem>)f.Deserialize(st);
}

Dictionary<int, ulong> stat = new Dictionary<int, ulong>();

foreach (var item in log)
{
if (stat.ContainsKey(item.domainIP))
{
stat[item.domainIP] += item.trafficSize;
}
else
{
stat.Add(item.domainIP, item.trafficSize);
}
}
domain.Add(stat);
}

private void DateStatisticsWorker(object state)
{
List<LogItem> log = new List<LogItem>();
string logPath = (string)state;
using (Stream st = new FileStream(logPath, FileMode.Open, FileAccess.Read))
{
IFormatter f = new BinaryFormatter();
log = (List<LogItem>)f.Deserialize(st);
}

Dictionary<DateTime, ulong> dic = new Dictionary<DateTime, ulong>();
foreach (var item in log)
{
if (dic.ContainsKey(item.date))
{
dic[item.date] += item.trafficSize;
}
else
{
dic.Add(item.date, item.trafficSize);
}
}
date.Add(dic);
}
}

Обсуждение

давно
Советник
400484
472
26.10.2017, 15:49
общий
это ответ
Здравствуйте, Посетитель - 399158!
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace rfpro
{
class Program
{
static void Main(string[] args)
{
// генерируем логи за интревал
LogFileGenerator gen = new LogFileGenerator();
gen.GenerateAndSave("D:\\logs", new DateTime(2017, 9, 13), new DateTime(2017, 9, 14));
// получаем статистику
LogStatistics logstat = new LogStatistics("D:\\logs");
logstat.UserStatistics();
logstat.DomainStatistics();
logstat.DateStatistics();

// сохраняем репорты
logstat.SaveUserStatReport("D:\\logs\\user_report.txt");
logstat.SaveDomainStatReport("D:\\logs\\domain_report.txt");
logstat.SaveDateStatReport("D:\\logs\\date_report.txt");
// ждем нажатия клавиши
Console.ReadKey(true);
}
}
[Serializable]
// класс точки лога
class LogItem
{
public DateTime date;
public int userIP;
public int domainIP;
public string domainName = "";
public ulong trafficSize;
public LogItem() { }
public LogItem(DateTime date, int userIP, int domainIP, string domainName, ulong trafficSize)
{
this.date = date;
this.userIP = userIP;
this.domainIP = domainIP;
this.trafficSize = trafficSize;
this.domainName = domainName;
}
}
// класс создания логов
class LogFileGenerator
{
List<string> letters = new List<string>() { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
List<string> domains = new List<string>() { ".com", ".ru", ".su" };
// генерируем статистику и сохраняем в файл
public void GenerateAndSave(string pathToSave, DateTime startDate, DateTime endDate)
{
Random rand = new Random();
List<List<LogItem>> logPackage = new List<List<LogItem>>();
int max = endDate.Day - startDate.Day; // считаем разницу дней
// цикл создания данных для max дней
for (int i = 0; i <= max; i++)
{
List<LogItem> list = new List<LogItem>();
// цикл создания точек даных для домена
for (int k = 0; k < rand.Next(2, 5); k++)
{
// генирируем имя дамена на основе списка letters
string domainname = "";
for (int j = 0; j < rand.Next(4, 10); j++)
{
domainname += letters[rand.Next(0, letters.Count - 1)];
}
domainname += domains[rand.Next(0, domains.Count - 1)]; // получаем расширение домена из списка domains
list.Add(new LogItem(startDate.AddDays(i), rand.Next(12345, 12350), rand.Next(45678, 45680), domainname, (ulong)rand.Next(1, 10))); // добавляем в писок новые данные
}
// сохраняем в файл
using (Stream st = new FileStream(pathToSave + "\" + startDate.AddDays(i).ToShortDateString() + ".log", FileMode.Create))
{
IFormatter f = new BinaryFormatter();
f.Serialize(st, list);
}
// цикл вывода информации из списка list на консоль
foreach (var l in list)
{
List<string> IP = new List<string>();
int mask = 255;
for (int j = 0; j < 4; j++)
{
IP.Add(((l.userIP >> j * 8) & mask).ToString());
}
IP.Reverse();
string uip = String.Join(".", IP);
IP.Clear();
for (int j = 0; j < 4; j++)
{
IP.Add(((l.domainIP >> j * 8) & mask).ToString());
}
IP.Reverse();
string dip = String.Join(".", IP);
Console.WriteLine(l.date.ToShortDateString() + " " + uip + " " + dip + " " + l.trafficSize);
}
}
}
}
// класс лога статистики
class LogStatistics
{
private List<Dictionary<int, ulong>> user = new List<Dictionary<int, ulong>>();
private List<Dictionary<int, ulong>> domain = new List<Dictionary<int, ulong>>();
private List<Dictionary<DateTime, ulong>> date = new List<Dictionary<DateTime, ulong>>();
public Dictionary<int, ulong> user_stat;
public Dictionary<int, ulong> domain_stat;
public Dictionary<DateTime, ulong> date_stat;
List<string> logFiles;
// коструктор класса
public LogStatistics(string logDir)
{
user_stat = new Dictionary<int, ulong>();
domain_stat = new Dictionary<int, ulong>();
date_stat = new Dictionary<DateTime, ulong>();
logFiles = new List<string>();
logFiles = System.IO.Directory.GetFiles(logDir, "*.log").ToList(); // получения списка файлов
}
// статистика по пользователю
public void UserStatistics()
{
var events = new List<ManualResetEvent>();
ThreadPool.SetMaxThreads(4, 4); // определение числа задач

// цикл перебора файлов
foreach (var file in logFiles)
{
// создание задачи
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(arg =>
{
UserStatisticsWorker(file);
resetEvent.Set();
});
events.Add(resetEvent);
}
WaitHandle.WaitAll(events.ToArray()); // ждем завершения все задач
Console.WriteLine("User stat done");
// цикл перебора пользователей
foreach (var piece in user)
{
// цикл получения данных по пользователю
foreach (var item in piece)
{
if (user_stat.ContainsKey(item.Key))
{
user_stat[item.Key] += item.Value;
}
else
{
user_stat.Add(item.Key, item.Value);
}
}
}
}
// статистика по домену
public void DomainStatistics()
{
var events = new List<ManualResetEvent>();
ThreadPool.SetMaxThreads(4, 4);
ThreadPool.SetMinThreads(4, 4);
foreach (var file in logFiles)
{
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(arg =>
{
DomainStatisticsWorker(file);
resetEvent.Set();
});
events.Add(resetEvent);
}
WaitHandle.WaitAll(events.ToArray());
Console.WriteLine("Domain stat done");
foreach (var piece in domain)
{
foreach (var item in piece)
{
if (domain_stat.ContainsKey(item.Key))
{
domain_stat[item.Key] += item.Value;
}
else
{
domain_stat.Add(item.Key, item.Value);
}
}
}
}
// статистика по дате
public void DateStatistics()
{
var events = new List<ManualResetEvent>();
ThreadPool.SetMaxThreads(4, 4);
foreach (var file in logFiles)
{
var resetEvent = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(arg =>
{
DateStatisticsWorker(file);
resetEvent.Set();
});
events.Add(resetEvent);
}
WaitHandle.WaitAll(events.ToArray());
Console.WriteLine("Date stat done");
foreach (var piece in date)
{
foreach (var item in piece)
{
if (date_stat.ContainsKey(item.Key))
{
date_stat[item.Key] += item.Value;
}
else
{
date_stat.Add(item.Key, item.Value);
}
}
}
}
// сохранение результатов по пользователю в файл
public void SaveUserStatReport(string dirPath)
{
string output = "";
foreach (var item in user_stat)
{
List<string> IP = new List<string>();
int mask = 255;
for (int i = 0; i < 4; i++)
{
IP.Add(((item.Key >> i * 8) & mask).ToString());
}
IP.Reverse();
output += String.Join(".", IP);
output += ": " + item.Value + "byte\r\n";
}
File.WriteAllText(dirPath, output);
}
// сохранение результатов по домену в файл
public void SaveDomainStatReport(string dirPath)
{
string output = "";
foreach (var item in domain_stat)
{
List<string> IP = new List<string>();
int mask = 255;
for (int i = 0; i < 4; i++)
{
IP.Add(((item.Key >> i * 8) & mask).ToString());
}
IP.Reverse();
output += String.Join(".", IP);
output += ": " + item.Value + "byte\r\n";
}
File.WriteAllText(dirPath, output);
}
// сохранение результатов по дате в файл
public void SaveDateStatReport(string dirPath)
{
string output = "";
foreach (var item in date_stat)
{
output += item.Key.ToShortDateString() + ": " + item.Value + "byte\r\n";
}
File.WriteAllText(dirPath, output);
}
// получение данных из файла для пользователей
private void UserStatisticsWorker(object state)
{
Console.WriteLine("user");
List<LogItem> log = new List<LogItem>();
string logPath = (string)state; // преобразуем в строку путь к файлу
//читаем файл
using (Stream st = new FileStream(logPath, FileMode.Open, FileAccess.Read))
{
IFormatter f = new BinaryFormatter();
log = (List<LogItem>)f.Deserialize(st); // десириализуем файл к типу данных List<LogItem>
}
// создаем словарь статистики по пользователям
Dictionary<int, ulong> stat = new Dictionary<int, ulong>();
foreach (var item in log)
{
if (stat.ContainsKey(item.userIP))
{
stat[item.userIP] += item.trafficSize;
}
else
{
stat.Add(item.userIP, item.trafficSize);
}
}
user.Add(stat);
}
// получение данных из файла для домена
private void DomainStatisticsWorker(object state)
{
Console.WriteLine("domain");
List<LogItem> log = new List<LogItem>();
string logPath = (string)state;
using (Stream st = new FileStream(logPath, FileMode.Open, FileAccess.Read))
{
IFormatter f = new BinaryFormatter();
log = (List<LogItem>)f.Deserialize(st);
}
Dictionary<int, ulong> stat = new Dictionary<int, ulong>();
foreach (var item in log)
{
if (stat.ContainsKey(item.domainIP))
{
stat[item.domainIP] += item.trafficSize;
}
else
{
stat.Add(item.domainIP, item.trafficSize);
}
}
domain.Add(stat);
}
// получение данных из файла для даты
private void DateStatisticsWorker(object state)
{
List<LogItem> log = new List<LogItem>();
string logPath = (string)state;
using (Stream st = new FileStream(logPath, FileMode.Open, FileAccess.Read))
{
IFormatter f = new BinaryFormatter();
log = (List<LogItem>)f.Deserialize(st);
}
Dictionary<DateTime, ulong> dic = new Dictionary<DateTime, ulong>();
foreach (var item in log)
{
if (dic.ContainsKey(item.date))
{
dic[item.date] += item.trafficSize;
}
else
{
dic.Add(item.date, item.trafficSize);
}
}
date.Add(dic);
}
}
}
давно
Посетитель
399158
228
31.10.2017, 19:49
общий
31.10.2017, 19:57
а можете рассказать как мы тут с потоками работаем вообще? как такое метод называется, семафор?
давно
Посетитель
399158
228
31.10.2017, 19:51
общий
и что тут значит [Serializable]?
давно
Советник
400484
472
01.11.2017, 09:12
общий
01.11.2017, 09:13
Цитата: Посетитель - 399158
и что тут значит [Serializable]?


Почитайте статьи:
- Сериализация и десериализация
- Object Serialization in the .NET Framework
давно
Посетитель
399158
228
01.11.2017, 09:14
общий
а про потоки расскажите что мы тут делаем?
давно
Посетитель
399158
228
01.11.2017, 09:20
общий
почему тут например
public void DomainStatistics()
{
var events = new List<ManualResetEvent>();
ThreadPool.SetMaxThreads(4, 4);
ThreadPool.SetMinThreads(4, 4);

два их?
давно
Советник
400484
472
01.11.2017, 11:38
общий
По потокам можно почитать тут.

метод SetMaxThreads(Int32, Int32). Задает количество запросов к пулу потоков, которые могут быть активными одновременно. Все запросы, превышающие это количество, остаются в очереди до тех пор, пока потоки пула не станут доступны.
метод SetMinThreads(Int32, Int32). Задает минимальное число потоков, создаваемых пулом потоков по требованию по мере поступления новых запросов перед переходом на алгоритм управления созданием и уничтожением потоков.

По сути вся работа с потоками сводится к следующему
Код:

var events = new List<ManualResetEvent>(); // создаем список событий
ThreadPool.SetMaxThreads(4, 4); // задает количество запросов к пулу потоков

// цикл перебора файлов
foreach (var file in logFiles)
{
// создание задачи
var resetEvent = new ManualResetEvent(false); // создаем новое событие
ThreadPool.QueueUserWorkItem( // помещает в очередь на выполнение
arg => // получаем объект. в данном случае будет задача
{
UserStatisticsWorker(file); // вызываем метод для подсчета статистики по пользователя из файла
resetEvent.Set(); // устанавливает состояние, что поток занят
});
events.Add(resetEvent); // добавляем в список потоков
}
WaitHandle.WaitAll(events.ToArray()); // ждем завершения все потоков


по ManualResetEvent почитать можно тут.

по симоформ можно вкрации почитать тут.
давно
Посетитель
399158
228
03.11.2017, 16:46
общий
а сам метод тут както называется, который мы используем с потоками?
Форма ответа