На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
  
> Сокет и ошибка 10038
    День добрый.
    Вообщем история такая. Есть два приложения - клиент и сервер. Вообщем всё классически. Трабл такого толка - когда клиент закрывает соединение на сервере сразу же после обработчика события OnClientDisconnect вываливается ошибка:
    Windows socket error: Сделана попытка выполнить операцию на объекте, не являющемся сокетом (10038), on API 'closesocket'
    При чём вываливается сразу в двух экземплярах. Код огромный - выкладывать его тут смысла нет. Вероятно на момент закрытия сокета он уже не существует исходя из толкования ошибки. С другой стороны он передаётся в обработчик, так что существовать должен, в дебаге видно даже его настройки. Проверено, что никакой другой кусок кода в этот момент не пытается работать с этим сокетом. Мысли есть?

    Добавлено
    Прошерстил гугль. Указанная ошибка встречается всего два раза. Оба пальцем в небо.
      Цитата DrMort @
      С другой стороны он передаётся в обработчик, так что существовать должен, в дебаге видно даже его настройки.
      Какое отношение обработчик события в компоненте VCL имеет к системному объекту? Системный объект видимо удален, экземпляр компонента остался. Любые попытки использовать системный объект через компонент будут давать ошибки(если компонент не будет самостоятельно пересоздавать системный объект, а он в данном случае не будет пересоздавать).
      Ну и исходник покажи.
      Хотя вообще-то странно. Не должен на сервере закрываться сокет, находящийся в режиме прослушивания.

      Эээ... Ты закрываешь сокет в OnClientDisconnect?
      Сообщение отредактировано: trainer -
        Указатели какие-нить не перезаписываешь? Что в дисконекте делается? Один поток в программе или нет?
          Никаких указателей не перезаписываю. В дисконнекте меняются просто флажки соединений - то есть в массив проставляется что васе пупкину больше ничего отсылать не стоит - мы его потеряли. Программа однопоточная - никаких специальных замутов наподобии CreateThread не делал. Сейчас попробую привести некий кусок кода
          ExpandedWrap disabled
            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 сервер и запустить серверное приложение. Если ошибка исчезнет - всему виной срада/операционка.
            Цитата DrMort @
            В дисконнекте меняются просто флажки соединений - то есть в массив проставляется что васе пупкину больше ничего отсылать не стоит - мы его потеряли

            И что разорванное соединение так и остается навсегда в массиве Connections или удаляется ?
            Следует иметь в виду, что клиентский сокет закрывается и удаляется автоматически после вызова OnClientDisconnect. Поэтому ни закрывать, ни освобождать самому Connections[i].Socket в OnClientDisconnect (и тем более до или после) нельзя, ну и ес-но нельзя обращаться к инвалидному указателю Connections[i].Socket после OnClientDisconnect

            Цитата DrMort @
            Программа однопоточная - никаких специальных замутов наподобии CreateThread не делал

            Чтобы прога стало многопоточной достаточно установить "замут" ServerType:=stThreadBlocking ;)
              Разорваное соединение остаётся, но никогда не используется. По прошествии некоторого времени по таймеру выбираются все разорваные соединения и удаляются из массива.
              Ещё раз - в OnClientDisconnect сокет вообще не трогается - процедура обработчика вообще может быть пустой. И тем более к указателю Connections[i].Socket никто не обращается. Дело все таки несколько в другом.
              Про ServerType:=stThreadBlocking мне тоже известно.
              Попробовал запустить сервер на другом компе где поднят SQL. Запустилась и нормально работает. Переставил винду. У меня по прежнему глючит. Возможно проблема с каким то драйвером. Мучаю дальше.
                Есть такая ситуация - что в режиме дебага многие среды при тестирование клиент-серверных приложений глючат.
                Поэтому я всегда рекомендую делать отладочные релизы и запускать как самостоятельные программы вне среды программирования......
                  Вне среды все равно глючит. Переставил винду - все та же ошибка. Завтра попробую переставить винду и не ставить ни одного драйвера.
                    Переставил винду поверх старой. Глючит. Форматнул винт - нормально. С дровами тоже нормально. Похоже что-то было с операционкой, может какие нить последствия лечения вирусни. Всем спасибо за мысли.
                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0287 ]   [ 16 queries used ]   [ Generated: 27.07.25, 22:15 GMT ]