Форум: "Сети";
Текущий архив: 2004.08.29;
Скачать: [xml.tar.bz2];
ВнизПроблема с разрывом socket соединения Найти похожие ветки
← →
Furyous © (2004-06-23 08:10) [0]Такая проблема: если в чате(ClientSocket) у клиента завершить процесс, то сервак выдаёт ошибку сокета и падает. Нужно как-то закрывать соединение с таким клиентом, но ничего не получается.
← →
Digitman © (2004-06-23 08:18) [1]
> сервак выдаёт ошибку сокета и падает
на то есть try..except
← →
Furyous © (2004-06-23 08:38) [2]Есть, а куда его вешать? На OnClientError не помогает.
← →
Digitman © (2004-06-23 08:59) [3]
> куда его вешать?
а мне почем знать. что у тебя там, в коде сервера, творится ?
считаешь, что я догадываться должен ?
← →
Furyous © (2004-06-23 16:37) [4]вот сервер:
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var s, c, l: string;
i: Integer;
fstream: tmemorystream;
begin
fstream := tmemorystream.Create;
s := Socket.ReceiveText;
if (Copy(s,1,2) = "#N") then begin
Delete(s,1,2);
ListBox1.Items.Add(s);
s := "#U";
for i := 0 to ListBox1.Items.Count - 1 do
s := s + ListBox1.Items[i]+";";
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText(s);
Exit;
end;
if (Copy(s,1,2) = "#M")or(Copy(s,1,2) = "#P") then begin
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText(s);
Exit;
end;
end;
{ if (Copy(s,1,2) = "#F") then
begin
ServerSocket1.Socket.Connections[0].SendStream(fstream);
end;}
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
var i: Integer;
begin
ListBox1.Items.Clear;
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText("#N");
end;
procedure TForm1.kickClick(Sender: TObject);
begin
ServerSocket1.Socket.Connections[ListBox1.ItemIndex].Close;
end;
procedure TForm1.ListBox1Click(Sender: TObject);
begin
Edit1.Text := ServerSocket1.Socket.Connections[listbox1.itemindex].RemoteAddress;
end;
procedure TForm1.FormCreate(Sender: TObject);
var IPIni: TIniFile;
begin
IPIni := TIniFile.Create(".\IP.ini");
port.text := IPIni.ReadString("Server", "Port", "1001");
IPIni.Free;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
c,l : string;
begin
SetLength(l, StrLen(PChar(c)) + 1);
StrLCopy(@l[1], PChar(c), Length(l) - 1);
DataSize := StrToInt(l);
Data := TMemoryStream.Create;
Delete(c, 1, Length(l));
Reciving:= true;
end;
procedure TForm1.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
var i: integer;
begin
// ListBox1.Items.Clear;
// ListBox1.Refresh;
// for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
// ServerSocket1.Socket.Connections[i].Close;
end;
← →
Digitman © (2004-06-23 17:26) [5]начни с изучения особенностей ПОТОЧНОГО протокола TCP/IP - в условиях глоб.сети эта чатообразная галиматья, бездумно содранная откуда-то и чуть "доработанная", функционировать ожидаемым образом не будет
для отслеживания нештатного обрыва "клиента" при исполнении обработчиков OnClientRead/OnClientWrite следует любые вызовы read/write-методов заключать в блок try..except, при возникновении исключения в блоке except выполнять Socket.Close и немедленно завершать дальнейшее выполнение обработчика
← →
Furyous © (2004-06-23 18:01) [6]Благодарю, надеюсь до пятницы успею...
← →
Snap © (2004-06-23 18:09) [7]А вообще переходи на Indy.
← →
Furyous © (2004-06-23 19:35) [8]Блин, всё-равно Socket Error и вылетевший юзер остаётся в юзер листе на серваке. Исключения воткнул везде, где надо, а не выходит =(
2Snap:
Пробовал, чёт не получалось. Мыльни примерчик если есть, желательно с отправкой файлов по локалке =) fjack@tut.by
← →
Furyous © (2004-06-23 19:37) [9]Блин, всё-равно Socket Error и вылетевший юзер остаётся в юзер листе на серваке. Исключения воткнул везде, где надо, а не выходит =(
2Snap:
Пробовал, чёт не получалось. Мыльни примерчик если есть, желательно с отправкой файлов по локалке =) fjack@tut.by
← →
Verg © (2004-06-23 19:54) [10]Я че-то не пойму. Это что тут?::
> procedure TForm1.Button3Click(Sender: TObject);
> var
> c,l : string;
> begin
>
> SetLength(l, StrLen(PChar(c)) + 1);
> StrLCopy(@l[1], PChar(c), Length(l) - 1);
> DataSize := StrToInt(l);
> Data := TMemoryStream.Create;
>
> Delete(c, 1, Length(l));
> Reciving:= true;
>
> end;
Бред какой-то....
← →
Verg © (2004-06-23 20:03) [11]
> [4] Furyous © (23.06.04 16:37)
> вот сервер:
> procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
> Socket: TCustomWinSocket);
> var s, c, l: string;
> i: Integer;
> fstream: tmemorystream;
> begin
> fstream := tmemorystream.Create;
> s := Socket.ReceiveText;
>
> if (Copy(s,1,2) = "#N") then begin
> Delete(s,1,2);
> ListBox1.Items.Add(s);
> s := "#U";
> for i := 0 to ListBox1.Items.Count - 1 do
> s := s + ListBox1.Items[i]+";";
> for i := 0 to ServerSocket1.Socket.ActiveConnections-1
> do
> ServerSocket1.Socket.Connections[i].SendText(s);
> Exit;
> end;
> if (Copy(s,1,2) = "#M")or(Copy(s,1,2) = "#P") then begin
> for i := 0 to ServerSocket1.Socket.ActiveConnections-1
> do
> ServerSocket1.Socket.Connections[i].SendText(s);
> Exit;
> end;
> end;
> { if (Copy(s,1,2) = "#F") then
> begin
> ServerSocket1.Socket.Connections[0].SendStream(fstream);
> end;}
Хм... У тебя на самом деле в коментариях SendStream? И на каждый ServerSocket1ClientRead зваодится по новому fstream := tmemorystream.Create;
который никто освобождать и не соьбирался?
А вообще опять: как же наконец объяснить, что размеры отправляемых порций НЕ РАВНЫ в общем случае размерам принимаемых при поточном обмене, коим является TCP/IP.
Они МОГУТ оказаться равными при некоторых "тепличных" условиях, но никогда на это расчитывать нельзя!
> s := Socket.ReceiveText;
>
> if (Copy(s,1,2) = "#N") then begin
Ну и что это за сравнения с #N, а если "приплыло" только #, а все остальное будет позже?
← →
Furyous © (2004-06-24 05:00) [12]#N - это юзера запросить имя, button3 бред, не обращай внимания. А fstream - это я для передачи файла делал, пока не пашет.
← →
Digitman © (2004-06-24 08:08) [13]ему про фому, он все про ерему гнет ..
> Furyous © (24.06.04 05:00) [12]
> #N - это юзера запросить имя
с чего ты взял, что первые два символа принятой по ReceiveText() строки обязательно будут равны или "#N" или "#M" или "#F" "#P" и ничему другому ?
← →
Furyous © (2004-06-24 08:21) [14]Потому что с них начинается любая мессага. Да чат, работает стабильно, тока надо баг убрать с вылетанием сервака.
← →
Digitman © (2004-06-24 09:12) [15]
> Furyous © (24.06.04 08:21) [14]
если клиент вызывом SendText() послал, например, строку "#N ВАСЯ ПУПКИН", это отнюдь не означает, что на сервере возникнет единственное событие OnClientRead(), и в обработчике этого события сервер вызовом ReceiveText() получит в точности такую же строку
представь себе ситуацию, что на сервере возникло, например, 3 последовательных события OnClientRead(), при этом
- в 1-м событии сервер получил строку "#N ВА"
- в 2-м событии сервер получил строку "СЯ ПУП"
- в 3-м событии сервер получил строку "КИН"
т.е. данные на сервер могут поступать отдельными фрагментами потока
если "склеить" эти 3 "фрагмента", то как раз и получится оригинальный отправленный клиентом текст "#N ВАСЯ ПУПКИН"
событий таких может возникнуть и более, заранее прогнозировать их число бессмысленно, гораздо более важно то, что последовательность отправляемых данных в точности соответствует последовательности принимаемых данных
в условиях интерсети это абсолютно реальная ситуация !!!
и вот теперь думай головой ... весь твой алгоритм - коту под хвост, когда ты его попытаешься использовать за рамками "тепличных" условий односегментной ЛВС.. да и в ЛВС рано или поздно алгоритм твой даст сбой из-за неучитывания тобой этих особенностей
← →
Evgeny V © (2004-06-24 09:17) [16]Для асинхронных сокетов exception можно поймать на уровне приложения, например использовать TApplicationEvents, и в OnException его отслеживать ESocketError
← →
Term (2004-06-24 09:53) [17]
> Digitman © (24.06.04 09:12) [15]
> - в 1-м событии сервер получил строку "#N ВА"
> - в 2-м событии сервер получил строку "СЯ ПУП"
> - в 3-м событии сервер получил строку "КИН"
и как быть в такой ситуации??? если количество частей на которые может распасться сообщение не известно???
← →
ValeraVV © (2004-06-24 10:06) [18]в начале перадавать размер сообщения, а в конце его контрольную сумму
← →
Digitman © (2004-06-24 10:17) [19]
> Term (24.06.04 09:53) [17]
например, см. [18]
контр.сумма, в принципе, необязательна
достаточно того, что принимающая сторона, получив сначала размер сообщения, знает с этого момента, сколько байт сообщения следует ожидать и может накапливать поступающие "порции" где-то во временном буфере до тех пор пока не будет принято полное ожидаемое сообщение, и только после этого анализировать врем.буфер
← →
Verg © (2004-06-24 11:16) [20]В чистом виде на разрыв соединения никаких ошибок не возникает и возникать не должно.
> то сервак выдаёт ошибку сокета и падает
Какую ошибку, конкретно?
← →
Furyous © (2004-06-24 13:12) [21]Asynchronous Socket Error 10053. В лучшем случае сервак просто закывает соединение со всеми.
← →
Verg © (2004-06-24 13:45) [22]Дело может быть в том, что на момент вызова ClientDisconnect список активных соединений еще содержит данное соединение. Т.о., ты рассылаешь сообщение всем, включая и того клиента, который отключился.
Методом postmessage перенеси рассылку сообщений всем из ServerSocket1ClientDisconnect в отдельную процедуру-обработчик.
← →
Furyous © (2004-06-24 13:58) [23]Чёт не выходит. Мона небольшой примерчик плз?
← →
Digitman © (2004-06-24 14:16) [24]
> Furyous © (24.06.04 13:58) [23]
> Чёт не выходит
а входит ?
не сподибишься ли показать, как ты это САМ пытаешься реализовать ?
← →
Furyous © (2004-06-24 14:46) [25]Я ваще не знаю как юзать postmessage. Там какие-то страные параметры, хз чё писать там.
← →
Digitman © (2004-06-24 14:56) [26]
> Там какие-то страные параметры
это какие же ?
← →
Furyous © (2004-06-24 15:03) [27](hwnd, cardinal, wparam, lparam)
← →
Digitman © (2004-06-24 15:05) [28]
> Furyous © (24.06.04 15:03) [27]
и что ?
у тебя с аглицким проблемы ?
← →
Furyous © (2004-06-24 15:08) [29]У меня хелп не пашет, ваще ни в какой проге хелп не пашет.
← →
Digitman © (2004-06-24 15:12) [30]
> Furyous © (24.06.04 15:08) [29]
не беда
на то есть оригинал - msdn.microsoft.com
← →
Furyous © (2004-06-24 15:26) [31]Да ладно, у меня MSDN 2001(на 3сд) и Visual Studio + MSDN 2003(на 5сд), а вот времени в обрез, завтра надо готовый чат с передачей файла сдать, но тут уже не до передачи файла, а хотя бы баг с дисконнектом убрать... блин
← →
Furyous © (2004-06-24 15:30) [32]я понимаю что надо было сразу смотреть, но я не знал что там это есть.
← →
Digitman © (2004-06-24 15:33) [33]
> времени в обрез, завтра надо готовый чат с передачей файла
> сдать
это твои проблемы, насчет "завтра"
я тоже не имею кучу времени разглагольствовать с тобой о превратностях жизни
← →
Furyous © (2004-06-24 15:43) [34]Во во, а лучше б помог =)
← →
Digitman © (2004-06-24 15:49) [35]
> Furyous © (24.06.04 15:43) [34]
вот-вот ...ты думать и работать в темпе вальса не хочешь, а я, видите ли, должен бросать все, оплачивать траффик и помогать лентяю
← →
Furyous © (2004-06-24 15:52) [36]А тебя сюда никто не тянет. И если у меня не получается - это не значит что я лентяй.
← →
Digitman © (2004-06-24 15:56) [37]
> Furyous © (24.06.04 15:52) [36]
разговор окончен
← →
Furyous © (2004-06-24 16:07) [38]ок
← →
Verg © (2004-06-24 17:40) [39]
> 25] Furyous © (24.06.04 14:46)
> Я ваще не знаю как юзать postmessage. Там какие-то страные
> параметры, хз чё писать там.
Странный ты, однако ващще....
Эта, программирование, говоришь? А может лутчче чё-нить другое, пока не поздно? ;)const
WM_DISCONNECT = WM_USER + 1;
type
TForm1 = class(TForm)
.............
procedure OnDisconnect(var Msg : TMessage); message WM_DISCONNECT;
.....
end;
...............
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
(*хз - не хз, а где педали-то находятся надо бы знать прежде, чем за руль
* садиться
*)
PostMessage(Handle, WM_DISCONNECT, 0, 0);
end;
procedure TForm1.OnDisconnect(var Msg : TMessage);
var i: Integer;
begin
for i := 0 to ServerSocket1.Socket.ActiveConnections-1 do
ServerSocket1.Socket.Connections[i].SendText("Хз кто, но кто-то отключился вапче. ");
end;
← →
Владимир (2004-06-24 17:43) [40]Надо выставить errorcode = 0 иначе ексепт.
procedure TForm1.ServerSocket1ClientError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
errorcode := 0;
end;
← →
APXi (2004-06-24 19:36) [41]У меня тоже такая проблема была и есть.
Кто хочет попробовать сделайте простейший сервер и клиента, откомпильте сервер и запускайте его НЕ из делфи, а клиента запустите из дельфи, соеденитесь, а потом просто прервите работу клиента (Run/Program Reset) ошибочка вылетит на сервере.
← →
Ne0z © (2004-06-24 20:37) [42]APXi ну Verg же все написал: нельзя закрывать сервак до выхода из обработчика OnClientDisconnect, так что посылаешь в этом обработчике свое сообщение PostMessage(Handle, WM_DISCONNECT, 0, 0); в обработчике котрого и закрывай сервак...
← →
Digitman © (2004-06-25 08:29) [43]
> Verg © (24.06.04 17:40) [39]
про "педали" - благодарю за поддержку
> Владимир (24.06.04 17:43) [40]
> Надо выставить errorcode = 0 иначе ексепт.
чушь
никакого "ексепта" без errorcode = 0 - просто будет выведено окно с диагностикой отказа
> APXi (24.06.04 19:36) [41]
> запускайте его НЕ из делфи, а клиента запустите из дельфи
при чем здесь "из делфи" или "НЕ из делфи" ?
← →
False_Delirium © (2004-06-25 15:18) [44]Люди грамотные в данной области с тобой разговаривают, а ты не пользуешься моментом.:)
При "OnSocketError" и "OnClientDisconnect" ты в первую очередь должен прекратить все операции с "клиентами", для которых был вызван обработчик.
В "OnSocketError" вставь как минимум
errorcode = 0 ; Socket.Close ;
это позволит тебе избавится от пугающих окошек с уведомлениями.
Одна из составляющий "педалей" находится в спецификации TCP/IP.
Блин, всё-равно Socket Error и вылетевший юзер остаётся в юзер листе на серваке. Исключения воткнул везде, где надо, а не выходит =(
Если клиент завершил работу аварийно или в ином роде некорректно, то следовательно он не смог передать серверной части запрос на завершений и обменяться подтверждающими сегментами. Поэтому твой сервер не определяет, что клиент "мёртв" до следующей попытки отправить данные клиенту.
Чтобы ты себе не усложнял задачу по надлежащей обработке поведения сервера при падении клиента, установи в "OnSocketError" то, что написано выше. И переодически посылай 1 контрольный символ, который никак не обрабатывается клиентом.
Обязательно введи контрольный буфер размера ожидаемых сообщений.
После того, как покажешь свой чат - удали его безвозвратно и начни с начала. Например - устройство протокола, далее исходные коды тех компонентов, которыми ты польуешься.
2DigitMan Приветствую, я видел как ты с самого начала появления на этом форуме помогал новичкам, как росла твоя квалификация и авторитет здесь. Но сейчас у меня складывается мнение, что тебе нужно отдохнуть и обуздать свою инициативу помочь каждому в каждом вопросе, если не хватает терпения на детальное объяснение.
Доказав, что ты специалист в данной области ты позволяешь себе небрежности в общении.
← →
Digitman © (2004-06-25 17:04) [45]
> False_Delirium © (25.06.04 15:18) [44]
> отдохнуть
с удовольствием
держи эстафетную палочку ?
> позволяешь себе небрежности в общении
не спорю ... когда тема скатывается до понимания того , что LMD, выдержки порой, увы, не хватает
← →
Verg © (2004-06-25 23:14) [46]
> [44] False_Delirium © (25.06.04 15:18)
Есть и у тебя "гонево"....
> Обязательно введи контрольный буфер размера ожидаемых сообщений.
>
> После того, как покажешь свой чат - удали его безвозвратно
> и начни с начала. Например - устройство протокола, далее
> исходные коды тех компонентов, которыми ты польуешься.
Ты это вообще, что ты хотел сказать-то?
Пробовал это вслух произнести? :)))
Я лично за водкой решил пойти после таких "откровений" :))
← →
Rouse_ © (2004-06-26 19:21) [47]К слову "Гонево"...
> Чтобы ты себе не усложнял задачу по надлежащей обработке
> поведения сервера при падении клиента, установи в "OnSocketError"
> то, что написано выше. И переодически посылай 1 контрольный
> символ, который никак не обрабатывается клиентом.
Это мы называем грамотный подход? Нет уж.. увольте...
← →
False_Delirium © (2004-06-28 11:15) [48]Rouse_ То, что написал я вообще никак не относится к грамотному программированию, а было сориентировано на "мне нужно к завтра"
Что же ты постишь, когда тема уже не актуальна и молчал со своими советами когда человек спрашивал в чём дело?
Verg :) ты прав, написал какую-то чушь.:)
2Digitman Палочка тяжеловата.:)
← →
McZim © (2004-06-28 11:18) [49]А что ваще у тебя сервак делает и как выглядет клиент
Страницы: 1 2 вся ветка
Форум: "Сети";
Текущий архив: 2004.08.29;
Скачать: [xml.tar.bz2];
Память: 0.59 MB
Время: 0.039 c