![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
ClientSocket и ServerSocket [D7, XP]
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;