Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
 Аватар для _Lamer
9 / 9 / 1
Регистрация: 16.11.2010
Сообщений: 33

Порт Ввода-вывода, ошибка записи в файл?

15.07.2012, 00:29. Показов 2203. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Суть такова: прога принимает файлы по TCP.
В серверной части испл.порт ввода-вывода (CreateIoCompletionPort, GetQueuedCompletionStatus), организован потоковый пул.
когда сервер обменивается с одним клиентом все работает, клиент передает а сервер принимет 100 файлов подряд и все ОК.
Но когда сервер принимает файлы от двух клиентов одновременно, то происходит следующее:
Сервер актептит клмента, ..... открывает файл
C++
1
2
3
m_hFile = CreateFile((LPCTSTR) pstrFilePath->GetString(), GENERIC_WRITE, NULL, NULL, 
                  CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED, NULL);
return (m_hFile != INVALID_HANDLE_VALUE);
связываю описатель файла с портом ввода-вывода
C++
1
fOk = (CreateIoCompletionPort(m_hFile, m_hIOCP, CompKey, dwNumberOfThread) == m_hIOCP);
затем сервер получает содержимое файла (по частям, размер буфера 1024 byte) из сокета (от клиента) и пишет в локальный файл на сервере
C++
1
2
3
4
5
6
7
BOOL fOk = ::WriteFile(m_hFile, (LPCVOID) m_pWbufSend->buf, dwBytesWrite, 
                        NULL, m_pOverlapSend);
if ( fOk == FALSE ) {
    if ( WSA_IO_PENDING != WSAGetLastError() )
        ThrowWSASocketException( WSAGetLastError() );
}
return ( FALSE );
И ТУТ ОШИБКА (try catch перехватывает вызов WriteFile), вставит TRACE-ы в код, вод лог вывода:
....
OpenFile m_hFile=0x1618. FilePath=c:\Out2\tmp\001.Client2_ToServe r.mdb. ThreadId=0x8f8.
CloseFile m_hFile=0x1618, FilePath=c:\Out2\tmp\001.Client2_ToServe r.mdb, ThreadId=0x8f8.
Close Soket pAcceptClient=0x3140000, ThreadId=0x8f8.

Create client pAcceptClient=0x2dd0000, ThreadId=0x8f8.
OpenFile m_hFile=0x1608. FilePath=c:\Out1\tmp\035.Client1_ToServe r.mdb. ThreadId=0x8f8.
CloseFile m_hFile=0x1608, FilePath=c:\Out1\tmp\035.Client1_ToServe r.mdb, ThreadId=0x8f8.
OpenFile m_hFile=0x160c. FilePath=c:\Out1\tmp\007.Client1_ToServe r.mdb. ThreadId=0x8f8.
CloseFile m_hFile=0x160c, FilePath=c:\Out1\tmp\007.Client1_ToServe r.mdb, ThreadId=0x8f8.

Create client pAcceptClient=0x2e40000, ThreadId=0xE18.
OpenFile m_hFile=0x1604. FilePath=c:\Out1\tmp\041.Client1_ToServe r.mdb. ThreadId=0x8f8.

CSocketException::GetErrMess. Error=Неверный дескриптор.
CSocketException::ShowMessageError. Error number=6.
Err. Descrip.="wsasocket.h. Line = 280. ". ThreadId=0x8f8.

Close Soket pAcceptClient=0x2dd0000, ThreadId=0x8f8.
CloseFile m_hFile=0x1604, FilePath=c:\Out1\tmp\041.Client1_ToServe r.mdb, ThreadId=0xE18.
OpenFile m_hFile=0x1604. FilePath=c:\Out2\tmp\003.Client2_ToServe r.mdb. ThreadId=0xE18.
CloseFile m_hFile=0x1604, FilePath=c:\Out2\tmp\003.Client2_ToServe r.mdb, ThreadId=0xE18.
OpenFile m_hFile=0x15f0. FilePath=c:\Out2\tmp\005.Client2_ToServe r.mdb. ThreadId=0xE18.
CloseFile m_hFile=0x15f0, FilePath=c:\Out2\tmp\005.Client2_ToServe r.mdb, ThreadId=0xE18.
....
помогите разобратся почему выскакивает ошибка, когда файл создается, описатель проверяется, ассоциируем с потртом - все ОК, потом пишем данные - ошибка на неправильный описатель (а перед этим заактептился еще один клиент, но до открытия своего файла (003.Client2_ToServer.mdb) еще вроде не дошел), закрываем файл-CloseHandle не ругается.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
15.07.2012, 00:29
Ответы с готовыми решениями:

Ошибка ввода/вывода 104 - файл не открыт для ввода
var a:array of integer; n,j,i,k: integer; f:text; begin assign(f,'C:\Users\Алла\Desktop\Универ\матрица.txt'); reset(f); ...

Ошибка ввода вывода 103: файл не открыт
Люди добрые выручите,завтра сдавать работу а я обнаружил ошибку при работе одной из процедур.Ошибка ввода/вывода 103: файл не...

Ошибка ввода/вывода 2: Не удается найти указанный файл
program dred9; USES CRT; TYPE rec=record n_rejsa:string; marsh:string; typeplane:string; station:string; price:real;

9
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
15.07.2012, 00:32
WINAPI никогда не использовал.
а так, подобную задачу можно реализовать сильно проще к красивше при использовании boost.asio.
0
 Аватар для _Lamer
9 / 9 / 1
Регистрация: 16.11.2010
Сообщений: 33
15.07.2012, 00:44  [ТС]
Цитата Сообщение от niXman Посмотреть сообщение
WINAPI никогда не использовал.
а так, подобную задачу можно реализовать сильно проще к красивше при использовании boost.asio.
суть в том, что требуется "читаь" и "писать" в дуплексе (одновременно), а значит многопоточная задача.
можно писать на чем угодно, но грабли будут если неправильно организовывать ввод-вывод в многопоточном приложении.
предложение хорошее, да и о библиотеке отзывы неплохие, но проект готов на 99%, и ты предлагаем ВСЕ НАФИГ И ЗАНОВО, да и со средой MinGW я не знаком.
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
15.07.2012, 00:48
Цитата Сообщение от _Lamer Посмотреть сообщение
а значит многопоточная задача.
не совсем так...
ибо пока ты не прочтешь, тебе нечего будет писать. а это намекает на однопоточность
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
15.07.2012, 19:41
затем сервер получает содержимое файла (по частям, размер буфера 1024 byte) из сокета (от клиента) и пишет в локальный файл на сервере
Где год вычитывания ключа из IOCP?

может у тебя оба файла к одному ключу прибиты?
0
 Аватар для _Lamer
9 / 9 / 1
Регистрация: 16.11.2010
Сообщений: 33
16.07.2012, 08:11  [ТС]
вот вызов
C++
1
pListenServer->GetStatus((PULONG_PTR)&pAcceptClient, &dwBytesTransfer/*, dwMilliseconds*/);
, вот реализация
C++
1
2
3
4
5
BOOL GetStatus(PULONG_PTR pCompKey, PDWORD pdwNumBytes, DWORD dwMilliseconds = INFINITE)    {
    LPWSAOVERLAPPED pOverlapped = NULL;
    DWORD dwResult = m_pIocp->GetStatus(pCompKey, pdwNumBytes, &pOverlapped, dwMilliseconds);
    return dwResult;
}
, в ключе передается сам клиент, онже хранит описатель файла, плюс ксасс ioData - который содержит буферы
ввода-выводы, структуры Overlapped, обрабатывает выделение и удаление памяти буферов и структур.
pOverlapped - чистая структура (не производняя с добавлением своих данных, как обычно Рихтер предлагает).

Добавлено через 12 минут
Цитата Сообщение от niXman Посмотреть сообщение
...ибо пока ты не прочтешь, тебе нечего будет писать. а это намекает на однопоточность
если смотреть на одного клиента то так, а я говорю о работе сервера сразу с несколькими клиентами, плюс то что клиент должен "уметь" одновреммено по одному сокету отправлять данные на сервер, а по другому принимать с сервера.
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
16.07.2012, 10:11
подожди. я может что-то забыл из этой всей IOCP, но вот тут:
C++
1
fOk = (CreateIoCompletionPort(m_hFile, m_hIOCP, CompKey, dwNumberOfThread) == m_hIOCP);
Ты кладешь m_hFile с ключом CompKey, а потом как ты получаешь этот хендл из GetQueuedCompletionStatus (ведь это на этот хендл ругается система, что он невалидный?)?
И кто такой у тебя pAcceptClient, который ты вытаскиваешь?
Свой старый код откопал (сервер, который сейчас крутится у брокера и обрабатывает тысячи клиентов одновременно).
Вот место:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void add( const HANDLE new_hdl, ULONG_PTR key ) {
    error_checker chker( WAPIE("IOCP::add") );
    m_handle = chker = CreateIoCompletionPort(new_hdl, m_handle.hdl(), key, 0);
}
 
// success = true
// timeout = false
// error = throw
bool wait( ULONG_PTR & key, DWORD &transferred, DWORD miliseconds) const {
    error_checker chker( WAPIE("IOCP::wait"), WAIT_TIMEOUT );
    LPOVERLAPPED  povl = NULL;
    BOOL res = chker = GetQueuedCompletionStatus(m_handle.hdl(), 
                &transferred, 
                &key, 
                &povl, miliseconds);
    return res ? true : false;
}
первый вызов кладет в очередь с определенным ключом, второй вынимает. потом, по ключу можно получить хендл, который я положил, ну это если у тебя ключ != хендл. если у тебя ошибка невалидный хендл с 2 клиентами, то ты явно что-то не то вынул.
0
 Аватар для _Lamer
9 / 9 / 1
Регистрация: 16.11.2010
Сообщений: 33
16.07.2012, 11:27  [ТС]
для порта ввода-вывода ключ - это указатель на клиента, который подключился к серверу = pAcceptClient.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
/////////////////////////////////////////////////////////////////////////////
// CAcceptClient
class CAcceptClient
{
....
private:
    ...
    IO_OPERATION_DATA* m_pioData;   //  Стуктура OVERLAPPED и буфер (см ниже)
    HANDLE m_hFile;
    ...
public:
    DWORD OpenFile...
    void CloseFile();
когда сервер актептит клиента
C++
1
2
3
4
PCAcceptClient pAcceptClient=(PCAcceptClient) VirtualAlloc(NULL, sizeof(CAcceptClient),...
...
// Ассоциируем  сокет клиента с портом завершения
m_pIocp->AssociateSocket( pAcceptClient->GetSocket(), (ULONG_PTR) pAcceptClient );
вот раелизация m_pIocp
C++
1
2
3
4
5
6
7
8
9
BOOL AssociateDevice(HANDLE hDevice, ULONG_PTR CompKey) {
  BOOL fOk=(CreateIoCompletionPort(hDevice, m_hIOCP, CompKey, dwNumberOfThread)==m_hIOCP);
  ASSERT(fOk);
  return(fOk);
}
 
BOOL AssociateSocket(SOCKET hSocket, ULONG_PTR CompKey) {
    return(AssociateDevice((HANDLE) hSocket, CompKey));
}
получается когда вызываем GetQueuedCompletionStatus (GetStatus)
C++
1
2
3
4
5
6
7
8
9
10
// Ожидаем завершения операции ввода/вывода  на любом сокете, связанным с данным портом
dwBytesTransfer= 0;
if ( dwResult=pListenServer->GetStatus( (PULONG_PTR)&pAcceptClient, &dwBytesTransfer ) ){
    if ( dwResult == (DWORD)-1 )
        ThrowWSASocketException;//  socket закрыт ПРОВЕРЕНО
    else
        dwBytesTransfer = 0;
    }
 
    ASSERT_POINTER(pAcceptClient, CAcceptClient);
GetQueuedCompletionStatus в переменной PULONG_PTR lpCompletionKey вернет указатель на pAcceptClient, а в каждом экземпляре pAcceptClient-а свои данные: m_hFile, m_pioData (в нем
C++
1
2
3
4
5
6
7
class IO_OPERATION_DATA /*: public OVERLAPPED*/
{
...
private:
    u_long          m_ulBuffBytes;
    LPWSAOVERLAPPED m_pOver;
    LPWSABUF        m_pwbuf;
) в pAcceprCliet определено IO_OPERATION_DATA* m_pioData; (см.выше)

Добавлено через 19 минут
villu,
вопрос, если у тебя абсолютно рабочий вариант с портом. расскажи пару моментов
1.что ты используешь в качестве ключа
2.ты испотльзуешь "читсую" сткуктуру OVERLAPPED или производный класс от OVERLAPPED (его обычно дополняют буфером...)
3.твой клиент использует одну структуру OVERLAPPED для записи и чтения в сокет или для записи своя а для чтения своя?
0
204 / 205 / 16
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
16.07.2012, 11:36
кажется понял. смотри код.
C++
1
2
3
4
5
wapi_file_handle f(L"C:\\tmp.txt");
    f.create();
    OVERLAPPED ovl;
    DWORD w;
    BOOL res = WriteFile(f.hdl(), "111", 3, &w, &ovl);// тут получим 6, хотя хендл живой
а тут:
C++
1
2
3
4
5
wapi_file_handle f(L"C:\\tmp.txt");
    f.create();
    OVERLAPPED ovl = {0}; // !!
    DWORD w;
    BOOL res = WriteFile(f.hdl(), "111", 3, &w, &ovl); // тут все ok, получаем или err=0 или err=997
Похоже, у тебя поле event в структуре не нулевое и вызов считает, что этот евент нужно дернуть

Добавлено через 5 минут
Цитата Сообщение от _Lamer Посмотреть сообщение
villu,
вопрос, если у тебя абсолютно рабочий вариант с портом. расскажи пару моментов
1.что ты используешь в качестве ключа
2.ты испотльзуешь "читсую" сткуктуру OVERLAPPED или производный класс от OVERLAPPED (его обычно дополняют буфером...)
3.твой клиент использует одну структуру OVERLAPPED для записи и чтения в сокет или для записи своя а для чтения своя?
1: в качестве ключа у меня так же указатель на объект клиента
2: производный, который, кстати в конструкторе забивается нулями ()
3: зависит от клиента. Есть клиенты, где у меня работа идет вопрос-ответ, тогда только одна, есть те, которые могут читать и писать "рандомно", в зависимости от внешних факторов. Там на сторону чтения свой, на запись свой.
1
 Аватар для _Lamer
9 / 9 / 1
Регистрация: 16.11.2010
Сообщений: 33
16.07.2012, 14:57  [ТС]
Цитата Сообщение от villu Посмотреть сообщение
OVERLAPPED ovl = {0}; // !!
а это вариант, я при вызове WSARecv данные обнулял а при записе в файл забыл.
ща запущу на тестирование, по результу отпишусь.

Добавлено через 3 часа 12 минут
villu, походу ОНО, обнулил эвент и все закрутилось, спасиб.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.07.2012, 14:57
Помогаю со студенческими работами здесь

Ошибка ввода/вывода 2: не удается найти указанный файл
Написал программу, файлы input.txt и output.txt создал(хранятся в одной папке с программой), Pascal ABC от администратора запустил, но...

Ошибка ввода/вывода 2: Не удается найти указанный файл
Program baza; Uses CRT; label rew; type spisok=record fam:string; imya:string; otch:string; adres:string; ...

Ссылка на порт ввода/вывода
typedef struct { volatile unsigned char *port_l; unsigned char pin_l; volatile unsigned char *port_r; unsigned...

Ошибка при работе с потоками ввода (вывода) в файл (из файла)
Изучаю перегрузку операторов ввода/вывода с файлом и без. Вылетает такая ошибка при отработанном коде: Необработанное исключение по...

Порт завершения ввода и вывода данных
Что из себя представляет порт завершения вывода данных? На некоторых сайтах пишут что это очередь overlapped дескрипторов,это правильное...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 30.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
Автоматическое создание документа при проведении другого документа
Maks 29.03.2026
Реализация из решения ниже выполнена на нетиповых документах, разработанных в конфигурации КА2. Есть нетиповой документ "ЗаявкаНаРемонтСпецтехники" и нетиповой документ "ПланированиеСпецтехники". В. . .
Настройка движения справочника по регистру сведений
Maks 29.03.2026
Решение ниже реализовано на примере нетипового справочника "ТарифыМобильнойСвязи" разработанного в конфигурации КА2, с целью учета корпоративной мобильной связи в коммерческом предприятии. . . .
Автозаполнение реквизита при выборе элемента справочника
Maks 27.03.2026
Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. При выборе "Спецтехники" (Тип Справочник. Спецтехника), заполняется. . .
Сумматор с применением элементов трёх состояний.
Hrethgir 26.03.2026
Тут. https:/ / fips. ru/ EGD/ ab3c85c8-836d-4866-871b-c2f0c5d77fbc Первый документ красиво выглядит, но без схемы. Это конечно не даёт никаких плюсов автору, но тем не менее. . . всё может быть. . .
Автозаполнение реквизитов при создании документа
Maks 26.03.2026
Программный код из решения ниже размещается в модуле объекта документа, в процедуре "ПриСозданииНаСервере". Алгоритм проверки заполнения реализован для исключения перезаписи значения реквизита,. . .
Команды формы и диалоговое окно
Maks 26.03.2026
1. Команда формы "ЗаполнитьЗапчасти". Программный код из решения ниже на примере нетипового документа "ЗаявкаНаРемонтСпецтехники" разработанного в конфигурации КА2. В качестве источника данных. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru