Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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
6-1088613132
4ebyrab
2004-06-30 20:32
2004.08.29
Webbrowser??? Как нажать на банер???


3-1091781022
Иванна
2004-08-06 12:30
2004.08.29
Возникает ошибка!


1-1092301873
Руслан
2004-08-12 13:11
2004.08.29
Еще один вопрос по EhDBGrid


14-1091953966
VID
2004-08-08 12:32
2004.08.29
Сразу четыре вопросов, насчёт администрирования Win2k


4-1089551383
DeMoN_Astra
2004-07-11 17:09
2004.08.29
Диалап соединение





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский