
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.188] |
![]() |
|
Сообщ.
#1
,
|
|
|
День добрый.
Вообщем история такая. Есть два приложения - клиент и сервер. Вообщем всё классически. Трабл такого толка - когда клиент закрывает соединение на сервере сразу же после обработчика события OnClientDisconnect вываливается ошибка: Windows socket error: Сделана попытка выполнить операцию на объекте, не являющемся сокетом (10038), on API 'closesocket' При чём вываливается сразу в двух экземплярах. Код огромный - выкладывать его тут смысла нет. Вероятно на момент закрытия сокета он уже не существует исходя из толкования ошибки. С другой стороны он передаётся в обработчик, так что существовать должен, в дебаге видно даже его настройки. Проверено, что никакой другой кусок кода в этот момент не пытается работать с этим сокетом. Мысли есть? Добавлено Прошерстил гугль. Указанная ошибка встречается всего два раза. Оба пальцем в небо. |
Сообщ.
#2
,
|
|
|
Цитата DrMort @ Какое отношение обработчик события в компоненте VCL имеет к системному объекту? Системный объект видимо удален, экземпляр компонента остался. Любые попытки использовать системный объект через компонент будут давать ошибки(если компонент не будет самостоятельно пересоздавать системный объект, а он в данном случае не будет пересоздавать).С другой стороны он передаётся в обработчик, так что существовать должен, в дебаге видно даже его настройки. Ну и исходник покажи. Хотя вообще-то странно. Не должен на сервере закрываться сокет, находящийся в режиме прослушивания. Эээ... Ты закрываешь сокет в OnClientDisconnect? |
Сообщ.
#3
,
|
|
|
Указатели какие-нить не перезаписываешь? Что в дисконекте делается? Один поток в программе или нет?
|
Сообщ.
#4
,
|
|
|
Никаких указателей не перезаписываю. В дисконнекте меняются просто флажки соединений - то есть в массив проставляется что васе пупкину больше ничего отсылать не стоит - мы его потеряли. Программа однопоточная - никаких специальных замутов наподобии CreateThread не делал. Сейчас попробую привести некий кусок кода
![]() ![]() void __fastcall TForm1::ServerSocket1ClientDisconnect(TObject *Sender, TCustomWinSocket *Socket) { int CurrentLocation=0,counter=0; int NumSym=0,i,o; AnsiString CurrName=""; for(i=0;i<MaxConnections;i++) //MaxConnections - константа содержащая максимальное число соединений с клиентами { if((Connections[i].Socket==Socket) && (Connections[i].Connected==true)) { if(Connections[i].Login!="") { Memo1->Lines->Add(Connections[i].Login+" disconnected"); CurrName=Connections[i].Login; CurrName=CurrName.Trim(); } else Memo1->Lines->Add("Non logined client disconnected"); Connections[i].Connected=false; Connections[i].Autorize=false; for(o=0;o<BufferLength;o++) Connections[i].SendBuffer[o]=""; Connections[i].BufferCounter=0; Connections[i].Idle=0; Form1->StatisticMonitor->Values["CurrentConnection"]=IntToStr(StrToInt(Form1->StatisticMonitor->Values["CurrentConnection"])-1); break; }; }; } Connections[] - массив структур содержащий сведения о соединениях, В нём есть поле Socket значение которого заполняется при установке связи. Но все это описание зряшное, потомучто содержимое обработчика можно полностью убрать и ничего не изменится - проверено. Так же пробовал в начале каждой процедуры имеющейся в проекте ставить стоп поинт и отслеживать что ещё происходит в момент когда клиент обрывает связь. Так вот ничего не происходит - сразу срабатывает OnClientDisconnect. Сразу после его срабатывания вылетает подряд две ошибки. Так что вероятнее всего дело не в исходном коде, а в настройках/багах проекта/операционной системы/среды программирования. Чуть позже попробую на чистом компе возвести SQL сервер и запустить серверное приложение. Если ошибка исчезнет - всему виной срада/операционка. |
Сообщ.
#5
,
|
|
|
Цитата DrMort @ В дисконнекте меняются просто флажки соединений - то есть в массив проставляется что васе пупкину больше ничего отсылать не стоит - мы его потеряли И что разорванное соединение так и остается навсегда в массиве Connections или удаляется ? Следует иметь в виду, что клиентский сокет закрывается и удаляется автоматически после вызова OnClientDisconnect. Поэтому ни закрывать, ни освобождать самому Connections[i].Socket в OnClientDisconnect (и тем более до или после) нельзя, ну и ес-но нельзя обращаться к инвалидному указателю Connections[i].Socket после OnClientDisconnect Цитата DrMort @ Программа однопоточная - никаких специальных замутов наподобии CreateThread не делал Чтобы прога стало многопоточной достаточно установить "замут" ServerType:=stThreadBlocking ![]() |
Сообщ.
#6
,
|
|
|
Разорваное соединение остаётся, но никогда не используется. По прошествии некоторого времени по таймеру выбираются все разорваные соединения и удаляются из массива.
Ещё раз - в OnClientDisconnect сокет вообще не трогается - процедура обработчика вообще может быть пустой. И тем более к указателю Connections[i].Socket никто не обращается. Дело все таки несколько в другом. Про ServerType:=stThreadBlocking мне тоже известно. Попробовал запустить сервер на другом компе где поднят SQL. Запустилась и нормально работает. Переставил винду. У меня по прежнему глючит. Возможно проблема с каким то драйвером. Мучаю дальше. |
Сообщ.
#7
,
|
|
|
Есть такая ситуация - что в режиме дебага многие среды при тестирование клиент-серверных приложений глючат.
Поэтому я всегда рекомендую делать отладочные релизы и запускать как самостоятельные программы вне среды программирования...... |
Сообщ.
#8
,
|
|
|
Вне среды все равно глючит. Переставил винду - все та же ошибка. Завтра попробую переставить винду и не ставить ни одного драйвера.
|
Сообщ.
#9
,
|
|
|
Переставил винду поверх старой. Глючит. Форматнул винт - нормально. С дровами тоже нормально. Похоже что-то было с операционкой, может какие нить последствия лечения вирусни. Всем спасибо за мысли.
|