Форум: "Сети";
Текущий архив: 2002.12.16;
Скачать: [xml.tar.bz2];
Вниз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;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.008 c