Форум: "Сети";
Текущий архив: 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;
Страницы: 1 2 вся ветка
Форум: "Сети";
Текущий архив: 2004.08.29;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.035 c