Недавно у меня появились идеи для нескольких проектов, которые связаны с чтением IP-адресов из файла. Поскольку все они должны иметь возможность обрабатывать большое количество хостов, я попытался реализовать многопоточность или создать пул сокетов и выбрать() из них, чтобы достичь некоторой формы параллелизма для лучшей производительности , В нескольких случаях чтение из файла кажется узким местом в повышении производительности. То, как я это понимаю, чтение из файла с помощью fgets или аналогичного - это синхронная операция блокировки. Поэтому, даже если я успешно выполнил клиент, который подключается к нескольким хостам асинхронно, операция будет по-прежнему синхронной, потому что я могу читать только один адрес за раз из файла.Чтение асинхронного ввода-вывода из файла
/* partially pseudo code */
/* getaddrinfo() stuff here */
while(fgets(ip, sizeof(ip), file) {
FD_ZERO(&readfds);
/* create n sockets here in a for loop */
for (i = 0; i < socket_num; i++) {
if (newfd > fd[i]) newfd = fd[i];
FD_SET(fd[i], &readfds);
}
/* here's where I think I should connect n sockets to n addresses from file
* but I'm only getting one IP at a time from file, so I'm not sure how to connect to
* n addresses at once with fgets
*/
for (j = 0; j < socket_num; j++) {
if ((connect(socket, ai->ai_addr, ai->ai_addrlen)) == -1)
// error
else {
freeaddrinfo(ai);
FD_SET(socket, &master);
fdmax = socket;
if (select(socket+1, &master, NULL, NULL, &tv) == -1);
// error
if ((recvd = read(socket, banner, RECVD)) <= 0)
// error
if (FD_ISSET(socket, &master))
// print success
}
/* clear sets and close sockets and stuff */
}
Я указал, мои проблемы с комментариями, но только уточнить: я не уверен, как выполнять асинхронные операции ввода/вывода на нескольких целевых серверах, считанных из файла, так как чтение записей из файла кажется быть строго синхронным. Я столкнулся с аналогичными проблемами с многопоточным процессом, с незначительным успехом.
void *function_passed_to_pthread_create(void *opts)
{
while(fgets(ip_addr, sizeof(ip_addr), opts->file) {
/* speak to ip_addr and get response */
}
}
main()
{
/* necessary stuff */
for (i = 0; i < thread_num; i++) {
pthread_create(&tasks, NULL, above_function, opts)
}
for (j = 0; j < thread_num; j++)
/* join threads */
return 0;
}
Это похоже на работу, но, поскольку несколько потоков обрабатывают один и тот же файл, результаты не всегда точны. Я предполагаю, что это связано с тем, что несколько потоков могут обрабатывать один и тот же адрес из файла одновременно.
Я рассмотрел загрузку всех записей из файла в массив/в память, но если файл был особенно большой, я думаю, что это может вызвать проблемы с памятью. Кроме того, я не уверен, что это даже имеет смысл делать в любом случае.
В качестве окончательного примечания; если файл, который я читаю, является очень большим файлом с огромным количеством IP-адресов, то я не считаю, что решение хорошо масштабируется. Что-то возможно с C, хотя, я полагаю, есть какой-то способ достичь того, что я надеюсь.
Чтобы суммировать это сообщение; Я хотел бы найти способ улучшить производительность приложений на стороне клиента, используя асинхронный ввод-вывод или многопоточность при чтении записей из файла.
Я чувствую вашу боль, но есть много способов прочитать файл. Самый быстрый подход, я знаю, включает в себя чтение файла последовательно с помощью собственных функций API (то есть ReadFile). Затем вы можете открутить обработку до разных потоков и т. Д. – Mikhail
Это бесполезно для чтения файла с несколькими потоками, прочитанного [this] (http://stackoverflow.com/a/10397184/7076153). У вас должен быть менеджер, который читает файл и передает каждому потоку строку файла. – Stargateur
В типичной системе Linux жесткий предел для максимального количества открытых дескрипторов (файлов и сокетов) обычно составляет 65536. (Мягкий предел, то есть по умолчанию, обычно намного ниже, примерно как 1024.) Даже если вы принимаете чрезвычайно длинные имена хостов и имена сервисов (для соединений, а не номера портов) вам все равно потребуется не менее 100 символов на каждого клиента. 65536 × 100 - всего около 6,5 мегабайт. Чтение и токенизация того, что (для пар хостов и портов) требуется только на долю секунды. ** Это незначительно. ** –