Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Виснет ClientSocket


Автор: bronenos 7.7.2007, 19:26
Использую ClientSocket компонент по такой схеме
Форма загружается:
  SSocket->Active = true;
Функция посыла введенных данных:
  SSocket->Open();
  SSocket->Socket->SendText(...);
Функция обработки onRead
  response = Socket->ReceiveText();
  Socket->Close();
Форма закрывается
  SSocket->Active = false;

При таком порядке действий сообщение доходит каждый второй раз. Первый раз нажимаю на кнопку оно доходит, второй раз нет, третий раз доходит, четвертый нет и так далее. Что в моей схеме неправильно?

Автор: Klin 7.7.2007, 21:09
bronenos, имхо от количества созданных одинаковых тем, увеличится только количество предупреждений.
Вам необходимо понимать, как работает каждая из функций. Прочитайте эту http://forum.vingrad.ru/forum/topic-48915/hl/clientsocket/index.html, возможно после этого поймете вашу ошибку.

Автор: bronenos 8.7.2007, 13:00
да я просто дважды видно кнопку нажал случайно, а там я не нашел ответа на проблему

Автор: Ak47black 8.7.2007, 13:50
bronenos, учти что сообшешения могут склеиваться при TCP.
Это происходит когда посылаешь очень часто один за другим пакетом. (Может конечно у тебя такое и небыть)
Тебе надо пометить на блоки и парсить все что приходит если ты будешь серьозно этим заниматься.

Автор: bronenos 8.7.2007, 14:35
вот попробуйте войти
Ник tester
Пасс test

http://phx.freedomf.net/c_chat/chat.exe
и отправить сообщение
первое отправит, второе нет, 3 да, 4 нет и так далее... вот в чем трабла
запросы раюотают через раз

(насчет неизвестных ошибок это остаток от дебага, скор уберу)

Автор: bronenos 8.7.2007, 20:48
Всем спасибо, проблема была в том, что я отправлял данные, когда сокет еще не соединился

Автор: Klin 9.7.2007, 05:56
Цитата(bronenos @  8.7.2007,  14:00 Найти цитируемый пост)
а там я не нашел ответа на проблему

Я хотел чтобы вы посмотрели на последовательность действий. Но рад, что вы сами нашли решение, действительно рад. К сожалению, сейчас пошла плохая тенденция, у многих программистов есть возможность, чтобы самим найти ответ, но думать что-то не хотят smile


ps. отметьте вопрос решенным.

Автор: bronenos 9.7.2007, 14:22
однако вторая проблема))
после подавления ошибки и вывода информации о ней (случаются теперь асинхронные ошибки) сокет перестает работать - открытие / закрытие не помогают... че делать?

Автор: bronenos 9.7.2007, 17:50
 smile как восстанавливать сокет после ошибки?  smile 

Автор: Ak47black 9.7.2007, 20:47
bronenos, надо онулировать его в процедуре обработки ошибок OnError, тоесть к переменной номера ошибки приравнять 0. 
Код

  ErrorCode = 0;

bronenos, по моему ты неправильно задаешь вопросы, мы тут не телепаты чтобы всё угадывать, выкладывай код или тестовый проект и описывай точно.
И прочитай сначала доки.

Автор: bronenos 9.7.2007, 22:20
каждые 2 секунды делаю запрос
Код

void __fastcall TCForm::CSend(TObject *Sender, TCustomWinSocket *Socket)
{
  Timer->Enabled = false;
  CSocket->Socket->SendText((AnsiString)
    "GET /c_chat/chat.php?id=" + last + " HTTP/1.0" "\r\n"
    "Host: phx.freedomf.net"                        "\r\n"
    "\r\n"
  );
}


недавно начали появляться асинхронные ошибки сокета... я сделал их подавление (Socket.onError)
Код

void __fastcall TCForm::CError(TObject *Sender, TCustomWinSocket *Socket,
      TErrorEvent ErrorEvent, int &ErrorCode)
{
  ErrorCode = 0;
}


ошибка не выскакивает, но и больше сообщения не грузятся, то есть работа сокета останавливается. как можно восстановить его работу после Asynchronous socket error? я искал ответа на вопрос полтора дня - пока не нашел....

Автор: Ak47black 9.7.2007, 23:47
bronenos, ты чтото нето там с этими сокетами делаешь.
Никаких подавлений в этом случае недолжен ты вообще делать, это только при попытке неправильно подсоединиться делают. 
(Я в Си не силён.)
Ты вообще тут полный код выложи ато никто не ответит.

Автор: bronenos 10.7.2007, 07:56
Полный код... я честно говоря не вижу в нем смысл... проблему я бы так сформулировал восстановление работоспособности сокета после Asynchronous Socket Error. Бывает, что случается ошибка во время запроса и страница не открывается, а через секунду все нормально. Вот видимо на такие моменты иногда попадает сокет и вылетает с ошибкой. Мне это надоело и я сделал подавление с попыткой CSocket->Close(); CSocket->Open(); его оживить, но не выходит.
Получается следующее.. после этой ошибки сокет перестает работать совсем, и мне эту работу надо восстановить чтоб сделать еще одну попытку запроса.

Автор: Ak47black 10.7.2007, 12:10
bronenos, чета я тогда непонимаю зачем ты закрываешь его если он даже небыл открыт в случае ошибки.
Сделай что-бы ошибка обнулировалась.
Если даже он такой глючиный там в Buildere (CSocket), тогда делай его в real time и в случае ошибки освобождай старый и создавай новый (компонент).

Цитата

Полный код...

Ну необязательно полный, сделай тестовый проект который отображает только ошибку.

Автор: bronenos 10.7.2007, 13:52
Вот что я делаю в случае ошибки (CSocket.onError)
Код

void __fastcall TCForm::CError(TObject *Sender, TCustomWinSocket *Socket,
      TErrorEvent ErrorEvent, int &ErrorCode)
{
  Area->Items->Add("Ошибка подключения");
  ErrorCode = 0;

  TClientSocket *CSocket;
  CSocket->Open();
}


А что надо делать, чтоб переменной CSocket присвоить новый сокет?
У меня получается, видимо, только локально его создать......

Автор: Ak47black 10.7.2007, 14:39
bronenos, ты работать с компонентами на программном уровне толком неумеешь.
Код

  TClientSocket *CSocket;
  CSocket->Open();
 
Почитай про объектное программирование и как правильно создавать и потом возвращайся.
Ты этот сокет даже не создал и ни присвоил адрес ни порт куда коннектиться. 
А вообще тут можно обойтись и без создания нового только ты чтото неправильно там делаешь, исходя из того как ты кодишь думаю так и есть smile .

Автор: bronenos 10.7.2007, 14:52
Я про ООП знаю. В PHP опыт имею, а про эти опции - ступил конкретно конечно, да не в этом наверное дело...
У Вас есть ICQ, можно туда стукнуть?

Автор: Ak47black 10.7.2007, 17:07
bronenos, ты можешь описать что ты вообще пытаешься сделать (для чего тебе сокеты нужны)? 

Автор: bronenos 10.7.2007, 17:44
почему все время bronenos является первым словом? =)
я делаю дополнение к своему веб-чату, и сокетами запрашиваю данные (+ руку набить), и все было бы путем, если бы после асинхронной ошибки сокет не переставал функционировать....

Автор: Ak47black 10.7.2007, 18:10
Короч я в Borlande Builder неособо разбираюсь, возьми переведи эту функцию на си
Код

function DownloadFile(const Url: string): string;

var

NetHandle: HINTERNET;

UrlHandle: HINTERNET;

Buffer: array[0..1024] of char;

BytesRead: cardinal;

begin

Result := '';

NetHandle := InternetOpen('Delphi 5.x', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);

 

if Assigned(NetHandle) then

   begin

 

     UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);

 

     if Assigned(UrlHandle) then

{ UrlHandle правильный? Начинаем загрузку }

       begin

         FillChar(Buffer, SizeOf(Buffer), 0);

         repeat

           Result := Result + Buffer;

           FillChar(Buffer, SizeOf(Buffer), 0);

           InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);

         until BytesRead = 0;

         InternetCloseHandle(UrlHandle);

       end

     else

       begin

{ UrlHandle неправильный. Генерируем исключительную ситуацию. }

         raise Exception.CreateFmt('Cannot open URL %s', [Url]);

       end;

 

     InternetCloseHandle(NetHandle);

   end

else

{ NetHandle недопустимый. Генерируем исключительную ситуацию }

   raise Exception.Create('Unable to initialize Wininet');

end;



http://forum.vingrad.ru/forum/topic-126761/unread-1/kw-%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%80-%D1%84%D0%B0%D0%B9%D0%BB%D0%B0-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B5/hl/internetopen/index.html есть чтото похожее и будет тебе счастье.
Эта функция запрашивает по адресу и возвращает html думаю это точто тебе нужно.
Перевести тут нетрудно. 

Автор: bronenos 10.7.2007, 20:07
я понял это так: "Нафиг тебе ClientSocket? Воспользуйся чем-нибудь другим."

Автор: Ak47black 10.7.2007, 20:24
bronenos,  да потомучто если ты этим путем пойдешь то тебе нужно изучить протокол передачи http и не одну команду надо передать(хотя незнаю может както и одной умудришься обойтись), а с этим нет.
Такчто переводи. Я им пользовался работает нормально.

Автор: bronenos 10.7.2007, 20:24
простите мою лень... нашел способ... проверять CClient->Socket->SocketHandle на условие больше нуля....

Добавлено @ 20:32
Код

    CSocket->Socket->SendText(
      "GET /c_chat/chat.php HTTP/1.0" "\r\n"
      "Host: phx.freedomf.net"        "\r\n"
      "\r\n"
    );


вот что я передаю

Автор: bronenos 10.7.2007, 21:39
радуюсь видимо рано...
все равно останавливается даже с новым сокетом

Код

if (CSocket->Socket->SocketHandle > 0)
{
  CSocket->Socket->SendText((AnsiString)
    "GET /" + Info->Path + "chat.php HTTP/1.0" "\r\n"
    "Host: " + Info->Host +                    "\r\n"
    "\r\n"
  );
}
else
{
  CSocket = new TClientSocket(NULL);
  Info->Init(CSocket);
  CSocket->Open();
}


Код

struct sInfo
{
  AnsiString Host;
  AnsiString Path;
  int Port;

  sInfo()
  {
    Host = "phx.freedomf.net";
    Path = "c_chat/";
    Port = 80;
  }

  void Init(TClientSocket *Socket)
  {
    Socket->Host = Host;
    Socket->Port = Port;
  }
};

sInfo *Info = new sInfo;

Автор: bronenos 11.7.2007, 16:03
надо же.. удалось окончательно рещить проблему, присвоив таки без ошибок новый объект класса переменной

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)