Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ClientSocket и ServerSocket [D7, XP]


Страницы:   1 2

Aleksandr ©   (2008-03-20 17:48:00) 

у меня два вопроса по сокетам )

1. отправляю сообщение
TMess = packed record

procedure TForm1.Button1Click(Sender: TObject);
var  Mess: TMess;
begin
 Mess.ID_DB:='3243643214364654645';
 Mess.ID_CLIENT:=strComp.Text;
 Mess.command:='send_mess';
 Mess.Txt:=strMess.Text;

 ClientSocket.Host:=strComp.Text;
 ClientSocket.Active:=true;
 ClientSocket.Socket.SendBuf(Mess,SizeOf(TMess));
 ClientSocket.Active:=false;
end;

почему сообщение отправляется только после того как я второй раз нажму на кнопку ?

2. принимаем сообщение
procedure TForm1.ServerSocketClientRead(Sender: TObject;
 Socket: TCustomWinSocket);
var
 buf: array[1..MaxSize] of byte;
 Size: Word;
 Mess: ^TMess;
begin
 memo1.Lines.Add('читаем');
 Size:=Socket.ReceiveLength; {Принимаемое кол-во байт}
 Socket.ReceiveBuf(buf,Size);
 New(Mess);
 BufToPct(Mess^,buf,Size);
 memo1.Lines.Add(Mess^.ID_DB);
 memo1.Lines.Add(Mess^.ID_CLIENT);
 memo1.Lines.Add(Mess^.command);
 memo1.Lines.Add(Mess^.Txt);
 memo1.Lines.Add('конец');
 Dispose(Mess);
end;

все нормально принимается, только после того как сообщение принялось у меня само приложение закрывается (. из чего это может быть ?


han_malign   (2008-03-21 12:35:00) [1]

Socket.ReceiveBuf(FBuf[FDepth], sizeof( FBuf) - FDepth)


han_malign   (2008-03-21 12:33:00) [2]

о - там еще и стек убивается на

buf: array[1.. MaxSize] of byte;
...
Size:=Socket.ReceiveLength; {Принимаемое кол-во байт}
Socket.ReceiveBuf(buf, Size);

поэтому EInvalidPointer может и не быть


> в Mess пусто и при попытке прочитать от туда
> memo1.Lines.Add(Mess.ID_DB); вылетает ошибка

- не нравится мне как ReceiveText реализован, на многоядерном можно грабли огрести

попробуй так
TForm1 = class(TForm)
...
private
   FDepth: integer;
   FBuf: array[word]of byte;
end;
...
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var offs: integer;
begin
  memo1.Lines.Add('читаем');
  inc(FDepth, Socket.ReceiveBuf(FBuf[FDepth], sizeof(FDepth) - FDepth));
  offs:= 0;
  while(FDepth - offs >= sizeof(TMess))do
  with( PMess(@FBuf[offs])^ )do begin
     memo1.Lines.Add(ID_DB);
     memo1.Lines.Add(ID_CLIENT);
     memo1.Lines.Add(command);
     memo1.Lines.Add(Txt);
     memo1.Lines.Add('конец');
     inc(offs, sizeof(TMess));
  end;
  dec(FDepth, offs);
  if( FDepth > 0 )then move(FBuf[offs], FBuf[0], FDepth);
end;

ну и неплохо бы иметь в пакете тэг(магическое слово) по которому можно начала пакета найти


Сергей М.   (2008-03-21 12:00:00) [3]


> han_malign ©   (21.03.08 11:48) [18]


Да просто стек засран)

Ты давай не глумись уже, автору не умные слова нужны про менеджеры памяти и прочую шнягу, а сделать так чтобы ошибка не "вылетала").. А отладчик ему что корове седло)


han_malign   (2008-03-21 11:48:00) [4]


> но после программа сама закрывается (
>



> > BufToPct(Mess^,buf,Size); // читаем все что только можно,
> >  а глядя на исходник этой функции я вижу, что в случае приема данных больше размером чем запись ты полезешь туда куда не надо

- после того как ты затер служебную информацию менеджера памяти для выделенного блока(конкретней - раньше там был повторный размер-флаг для валидации(сечас там кажется прямые ссылки для двусвязного списка - глубоко не копался еще) ) данными превышающими размер буфера, на Dispose(Mess) - возникает Invalid pointer operation(EInvalidPointer).
На нем все и вылетает, а вот хлопнет ли при этом дверью - зависит от того насколько целостность кучи повреждена - на экземпляр класса EInvalidPointer тоже память выделять надо...

З.Ы. Ситуатции с "теряющимися исключениями" плотно не отлаживал - поэтому насчет памяти под экземпляр исключения - чисто предположение...

З.З.Ы. На  memo1.Lines.Add - алокируются временные строки, но видимо менеджер памяти находит место не доходя до разрушенной цепочки(пока везет)... Так что - могло вылетать и до последней строки.


Aleksandr   (2008-03-21 11:25:00) [5]

в Mess пусто и при попытке прочитать от туда
memo1.Lines.Add(Mess.ID_DB); вылетает ошибка


Slym   (2008-03-21 10:45:00) [6]

while length(InBuffer) >=SizeOf(Mess) do


Slym   (2008-03-21 10:44:00) [7]

var InBuffer:string;
procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
 s:string;
 Mess:TMess;
begin
memo1.Lines.Add('читаем');
InBuffer:=InBuffer+Socket.ReceiveText;
while length(InBuffer)>SizeOf(Mess) do
begin
 s:=copy(InBuffer,1,SizeOf(Mess));
 delete(InBuffer,1,SizeOf(Mess));
 move(PChar(s)^,Mess,SizeOf(Mess);
 memo1.Lines.Add(Mess.ID_DB);
 memo1.Lines.Add(Mess.ID_CLIENT);
 memo1.Lines.Add(Mess.command);
 memo1.Lines.Add(Mess.Txt);
 memo1.Lines.Add('конец');
end;
end;


Сергей М.   (2008-03-21 10:39:00) [8]


> я отладчиком прошелся по коду приемы сообщения
> и не чего там не увидел


Значит не туда смотрел, раз не увидел.

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


Aleksandr   (2008-03-21 10:35:00) [9]

да дело в том что я отладчиком прошелся по коду приемы сообщения
и не чего там не увидел, отрабатывается последняя строчка и программа сама закрывается (


Сергей М.   (2008-03-21 10:29:00) [10]


> может хватит глумится


А сам-то не глумишься ?

У тебя под рукой есть отладчик, вот и воспользуйся им для поиска ошибки.

И компоненты эти вовсе ни причем - с тем же "успехом" можно долго и нудно канючить помощь в поиске ошибки в программе, использующей любой иной компонент.


Aleksandr   (2008-03-21 10:24:00) [11]

может хватит глумится, подскажите что надо делать, где искать )

желательно с примерами, если не затруднит )


Сергей М.   (2008-03-21 09:53:00) [12]


> с сокетами вообще работаю раз второй


А с отладчиком какой ?


Aleksandr   (2008-03-21 09:47:00) [13]

сообщение принимается, этот код отрабатывается
memo1.Lines.Add(Mess^.ID_DB);
memo1.Lines.Add(Mess^.ID_CLIENT);
memo1.Lines.Add(Mess^.command);
memo1.Lines.Add(Mess^.Txt);
memo1.Lines.Add('конец');

но после программа сама закрывается (


Aleksandr   (2008-03-21 09:45:00) [14]

все выслушал, спасибо за критику )

я новичек, а с сокетами вообще работаю раз второй ))
так прошу помочь и подсказать что где надо сделать

TMess = packed record
 ID_DB: string[32];
 ID_CLIENT: String[50];
 command: String[50];
 Txt: String[200];
 end;

спасибо за помощь )


Slym   (2008-03-21 05:37:00) [15]

Palladin ©   (20.03.08 18:09) [5]
+1...
если string то, передается не строка, а указатель на нее :) всеравно что копировать файлы на др комп "ярлычком" на него :)


Slym   (2008-03-21 05:10:00) [16]

режим работы ClientSocket не озвучен, но судя по ServerSocketClientRead - всетаки неблокирующий режим, а в неблокирующем режиме так делать нельзя:
ClientSocket.Active:=true;
ClientSocket.Socket.SendBuf(Mess,SizeOf(TMess));// <<нет гарантии что Active=true
ClientSocket.Active:=false;


Palladin   (2008-03-20 18:09:00) [17]

да и кстати какого типа поле TMess.Txt и TMess.command ?


Palladin   (2008-03-20 18:09:00) [18]

так проверяй, проверяй результат приема/отправки данных, это раз.

два: ты чего творишь в приеме?

procedure TForm1.ServerSocketClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
buf: array[1..MaxSize] of byte;
Size: Word;
Mess: ^TMess;
begin
memo1.Lines.Add('читаем');
Size:=Socket.ReceiveLength; {Принимаемое кол-во байт}
Socket.ReceiveBuf(buf,Size);
New(Mess); // память выделена только под одну запись
BufToPct(Mess^,buf,Size); // читаем все что только можно, а глядя на исходник этой функции я вижу, что в случае приема данных больше размером чем запись ты полезешь туда куда не надо
memo1.Lines.Add(Mess^.ID_DB);
memo1.Lines.Add(Mess^.ID_CLIENT);
memo1.Lines.Add(Mess^.command);
memo1.Lines.Add(Mess^.Txt);
memo1.Lines.Add('конец');
Dispose(Mess);
end;


что за безолаберность вообще?


Aleksandr   (2008-03-20 18:03:00) [19]

"почему сообщение отправляется только после того как я второй раз нажму на кнопку ?"

решил так, потому что пробовал передовать обычные тесктовые сообщения и сервер принимал их только после того как я нажимал второй раз на кнопку )


Aleksandr   (2008-03-20 18:02:00) [20]

procedure BufToPct(var Packet; var buf; Size: Word);
{Конвертация из буфера в пакет}
var
 arPacket: array[1..MaxSize] of byte absolute Packet;
 arBuf: array[1..MaxSize] of byte absolute buf;
 i: Word;
begin
 for i:=1 to Size do
   arPacket[i]:=arBuf[i];
end;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо