Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.08.29;
Скачать: CL | DM;

Вниз

Проблема с разрывом 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;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.05 c
10-1033103025
KA_
2002-09-27 09:03
2004.08.29
CORBA-сервер "жрет" память


1-1092455709
race1
2004-08-14 07:55
2004.08.29
окно и размер


1-1092242118
Frozzen
2004-08-11 20:35
2004.08.29
Преобразование типов


6-1088318929
SergP
2004-06-27 10:48
2004.08.29
TServerSocket. Как узнать порт?


14-1092206336
Labert
2004-08-11 10:38
2004.08.29
С чего вы начинали?