Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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
14-51928
vaneks
2002-11-25 13:01
2002.12.16
Системные папки МастДай


3-51654
ds
2002-11-28 18:07
2002.12.16
Удаление записей


3-51620
shelest
2002-11-28 11:03
2002.12.16
OLE DB и Oracle


6-51862
Romych
2002-10-21 12:26
2002.12.16
Socket - Никак не пойму


14-51946
Кен
2002-11-21 03:10
2002.12.16
Как конвертировать DLL в Дельфи? Чтобы можно было чуть чуть подпр





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский