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

Вниз

TNMMsg+TNMMsgServ   Найти похожие ветки 

 
kostik78ua   (2002-10-18 10:38) [0]

На клиенте происходят события (запуск программ), которые через TNMMsg отправляются месседжеми на сервер. Там TNMMsgServ принимает и пишет в БД.
И все бы ничего, но когда много событий происходят одновременно, создается впечатление что сервер (TNMMsgServ) "захлебывается".
Выдает сообщение либо ошибка доступа, либо "10038 socket operation non-socket".
В чем глюк и как его обойти?


 
Digitman ©   (2002-10-18 11:42) [1]

"Глюк", скорее всего, в твоем коде, а не в коде компонентов.
А без твоего кода трудно сказать, "как его обойти"

Будет код - будет и анализ/рекомендации.


 
kostik78ua   (2002-10-18 15:17) [2]

// ************* Клиент (вырезки) *************

type
tstr = string;
ptstr = ^tstr;
var
frmClient: TfrmClient;
List: TList; {Организовую очередь из сообщений, которые пойдут на сервер}
{В дальнейшем из TList будем последовательно выбирать месседжи и делать PostIt}
WM_MYKEYHOOK: cardinal;

{*** Инициализация}
procedure TfrmClient.FormCreate(Sender: TObject);
begin
WM_MYKEYHOOK := RegisterWindowMessage("WM_MYKEYHOOK");
List:=TList.Create;
NMMsg1.Port:=7702;
NMMsg1.Host:="MyServerHost";
NMMsg1.FromName:="MyClientHost";
end;
{*** Инициализация}

{***Вспомогательные функции}
procedure AddElem(str1: string);
var
elem: ptstr;
begin
GetMem(elem, 250);
elem^:=str1;
List.Add(elem);
end;
procedure RemoveElem(elem: ptstr);
begin
elem:=ptstr(List.Items[0]);
FreeMem(elem, 250);
List.Remove(elem);
end;
{***Вспомогательные функции}

{***Обработка события}
procedure TfrmClient.WndProc(var Msg: TMessage);
var
Buffer: array [0..255] of char;
begin
inherited ;
if Msg.Msg = WM_MYKEYHOOK then // Событие возникает когда запускается приложение (Хотя может быть и что-то другое)

begin
Buffer := "Формируем строку";
AddElem(Buffer); // Добавили в TList
end;
end;
{***Обработка события}

{***По таймеру проверяем TList и отсылаем месседжи}
procedure TfrmClient.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled:=false;
while List.Count>0 do
begin
NMMsg1.PostIt(tstr(List.Items[0]^));
RemoveElem(ptstr(List.Items[0]));
end;
List.Capacity:=List.Count;
Timer1.Enabled:=true;
end;

procedure TfrmClient.FormDestroy(Sender: TObject);
begin
List.Free;
end;

// ****************** Сервер **********************

procedure TfrmServer.FormCreate(Sender: TObject);
begin
NMMSGServ1.Port:=7702;
NMMSGServ1.Host:="MyServerHost";
AssignFile(F, "c:\k1.txt");
Rewrite(F);
end;

procedure TfrmServer.NMMSGServ1MSG(Sender: TComponent; const sFrom,
sMsg: String);
begin
Writeln(F, sFrom+"::"+sMsg);
end;

procedure TfrmServer.FormDestroy(Sender: TObject);
begin
CloseFile(F);
end;




 
Digitman ©   (2002-10-18 15:47) [3]

Поясни для начала вот это

{***Вспомогательные функции}
procedure AddElem(str1: string);
var
elem: ptstr;
begin
GetMem(elem, 250); // для чего под указатель выделяется аж 250 байт ? Что есть эти самые 250 байт ?
elem^:=str1; // что здесь по-твоему происходит ?
List.Add(elem);
end;


 
kostik78ua   (2002-10-18 16:10) [4]

GetMem(elem, length(str1)); // Наверное лучше написать так. Но это не критично. str1 - у меня < 250 байт
elem^:=str1; // Здесь в выделенную память (250 байт) по адресу elem заносится строка. А что не так?

И опять же это не главный вопрос. Здесь все работает. Срыв коннекта происходит когда я начинаю слать WM_MYKEYHOOK из нескольких приложений одновременно (при чем в цикле).


 
Digitman ©   (2002-10-18 16:27) [5]

>>GetMem(elem, length(str1)); // Наверное лучше написать так

С чего бы это лучше ? размер указателя в Win32 всегда равен SizeOf(pointer) = 4

>>Но это не критично

Дело не в этом) ... Когда-нибудь, не разобравшись сейчас с указателями, ты получишь проблемы с нехваткой/утечкой памяти.
А пока - да, это вроде бы не критично : там, где требуется 4 байта, запрашивать 250 байт

>>когда я начинаю слать WM_MYKEYHOOK из нескольких приложений одновременно

Ты осознаешь при этом, что каждый процесс имеет свое виртуальное адресное пространство (ВАП) ? Или это для тебя пока - пустой звук ?


 
kostik78ua   (2002-10-18 16:42) [6]

С ВАПом я конечно же знаком.
Ну и что??? Я отлично генерирую и обрабатываю событие.
Handle окна - не зависит от ВАП. Именно ему я и посылаю WM_MYKEYHOOK. А дальше через TMNMsg отсылаю строку. Оно работает, пока сообщений WM_MYKEYHOOK не становится много за один момент времени.


 
Digitman ©   (2002-10-18 16:52) [7]

>>Handle окна - не зависит от ВАП.
Причем здесь хэндл окна ? не о нем речь.

>>Именно ему я и посылаю WM_MYKEYHOOK

Ну да, разумеется ! Из другого процесса с совершенно иным ВАП !
И параметром что передаешь в SendMessage() ?

Вот эта строка
Buffer := "Формируем строку";
ведь не ее на самом деле ты пишешь в файл-то , наверно ?
Что-то ведь, скорее всего, получаешь через wParam,lParam в WndProc() ? Так вот - что и как конкретно ?



 
kostik78ua   (2002-10-18 17:21) [8]

Сейчас я написал небольшую тестовую програмульку.

procedure TfrmTest.FormCreate(Sender: TObject);
begin
WM_MYKEYHOOK := RegisterWindowMessage("WM_MYKEYHOOK");
end;
procedure TfrmTest.Button1Click(Sender: TObject);
var
i: integer;
begin
for i := 1 to 100 do
begin
SendMessage(<Handle клиента>, WM_MYKEYHOOK, Handle, i);
Sleep(10);
end;
end;

И запускаю ее несколько экземпляров. При этом запущено столько же клиентов.

в Buffer-е у меня имя exe-файла, который я выцепляю из Хэндла=Msg.WParam

AddElem(IntToStr(Handle)+"::"+Buffer+IntToStr(Msg.LParam));


 
Digitman ©   (2002-10-18 17:32) [9]


> в Buffer-е у меня имя exe-файла, который я выцепляю из Хэндла=Msg.WParam


Откуда "имя exe-файла" появилось в Msg.WParam ? Я не вижу нигде это в приведенном коде передатчика сообщения. Вижу, что посылаешь разного рода значения орд.типов, но - никак не строковых. А "имя exe-файла", сдается мне, таки строковый тип данных)



 
kostik78ua   (2002-10-18 17:44) [10]

Если хочешь, выведу я весь WndProc. Хотя мне кажется это к вопросу не относится. Глюк все равно на уровне компонент TNMMsg.

procedure TfrmClient.WndProc(var Msg: TMessage);
const
MaxPath = 255;
type
TPath = array [0..MaxPath] of char;
var
Buffer: TPath;
dwProcessId: Cardinal;
hInst: Cardinal;
hProcess: Cardinal;
begin
inherited ;
if Msg.Msg = WM_MYKEYHOOK then
begin
FillChar(Buffer, MaxPath, #0);
if IsNT4Plus then begin
hInst:=GetWindowLong(Msg.WParam, GWL_HINSTANCE);
GetWindowThreadProcessId(Msg.WParam, @dwProcessId);
hProcess:=OpenProcess(PROCESS_ALL_ACCESS, false, dwProcessId);
if hProcess > 0 then
try
GetModuleFileNameEx(hProcess, hInst, Buffer, MaxPath);
finally
CloseHandle(hProcess);
end;
end
else GetWindowModuleFileName(Msg.WParam, Buffer, MaxPath);

StrCopy(Buffer, AnsiUpper(PChar(ExtractFileName(Buffer))));

AddElem(IntToStr(Handle)+"::"+Buffer+IntToStr(Msg.LParam));
end;
end;


 
Digitman ©   (2002-10-18 18:00) [11]

Ага ... т.е. ты возложил на процесс-приемник обязанность по определению имени файла хост-процесса-передатчика ? Понятно. Иными словами, содержимое Buffer формируется искл-но в ВАП процесса-приемника...

Та-а-ак ... начинается remote debugging

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


 
kostik78ua   (2002-10-18 18:17) [12]

На сервере
Project prjServer.exe raised exception class EAccessViolation with message "Access violation at address 00441484 in module "prjServer.exe". Write of address 00DA91B4". Process stoped.

На клиенте
Connection failed

Причем:
1-й клиент успел передать 83 строку
2-й клиент успел передать 10 строк
3-й и 4-й только запустились


 
Digitman ©   (2002-10-20 13:15) [13]

Теперь стартуй приложение-сервер (собранное с опциями отладки) под управлением Делфи-отладчика и тут же вызывай Search | Find Error ...

Введи этот адрес - 00441484, отладчик покажет строку исх.текста, вызвавшую это исключение. О результатах сообщи.



Страницы: 1 вся ветка

Текущий архив: 2002.12.16;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.016 c
8-51835
kima
2002-08-24 20:22
2002.12.16
gif


1-51809
Дмитрий К.К.
2002-12-05 08:16
2002.12.16
Exception EOleSysError


6-51875
kofman
2002-10-21 01:03
2002.12.16
Как прочитать строчку из файла с сервера?


3-51603
SemFLY
2002-11-27 23:40
2002.12.16
Database Desktop, но что лучше для MySQL


3-51592
ev1972
2002-11-27 11:39
2002.12.16
Как обрезать картинки при выводе в FastReport?