Форум: "Сети";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.02.04;
Скачать: [xml.tar.bz2];




Вниз

Socket, помогите с NMStrm 


Kuzmin_Alex   (2001-10-30 00:38) [0]

Здраствуйте Господа.
Использую NMStrm и NMStrmServer для передачи JPEG, пока сервер читает -> рисует картинку и т.п. он ничего не может принимать. Как запустить обработку буфера в фоновом режиме, чтобы сервер был всегда готов.
Спасибо.



Polevi   (2001-10-30 11:08) [1]

У меня есть подозрение что NMStrmserver для каждого нового клиента создает новый поток - и поэтому в "ничего не может принимать" мне както не верится



sedoy   (2001-10-30 13:09) [2]

Вот именно, может ты рисуешь в onread???



Kuzmin_Alex   (2001-10-30 20:09) [3]

Именно там я и рисую. А где и как надо?



Digitman   (2001-10-31 11:40) [4]

в OnRead буферизуй принятые фрагменты потока ("картинка" ведь не целиком приходит, а последовательными фрагментами) где-нибудь в памяти.
Когда "картинка" принята целиком, создавай доп.поток, и передавай ему , например, в конструкторе адрес буфера с картинкой - пусть он занимается построением картинки параллельно. Не забывай о синхронизации доп.потока с основным в момент обращения к методам собственно визуализации построенной "картинки"



Kuzmin_Alex   (2001-10-31 18:38) [5]

Ok это все понятно. Тогда такой вопрос: пускай буфером будет TMemoryStream, как тогда убить часть данных, например только что прочитанных, а не просто переместить указатель?



Polevi   (2001-11-01 08:29) [6]

Создай новый TMemoryStream - буфер
из старого буфера скопируй в него что нужно, а старый удали



Digitman   (2001-11-01 10:27) [7]

>Kuzmin_Alex
Не понял - зачем их "убивать" ? Тебе же в буфере в результате нескольких обработок OnRead нужно получить данные, соответствующие очередной полностью переданной картинке, прежде чем передать в поток содержимое буфера на построение этой картинки ?



Kuzmin_Alex   (2001-11-01 15:53) [8]

Сейчас объясню, что мне надо. NMStrm (на удаленной машине) в цикле отсылает наименоваие запущенного процесса (в SFrom) + иконку (в Stream) соответствующую этому процессу (так хочет мой Boss).
Для приема написан следующий код:

procedure TSE.NMStrmServ1MSG(Sender: TComponent; const sFrom: String;
strm: TStream);
var
MyFStream: TMemoryStream;
icon:TIcon;
begin

if copy(sFrom,2,2)=":\" then
begin
ProcessStream := TMemoryStream.Create;
Icon:=TIcon.Create;
try
MyFStream.CopyFrom(strm, strm.size);
MyFStream.position:=0;
icon.LoadFromStream(MyFStream); //получаем иконку
with lvProcList.Items.Add do //добавляем в список
begin
Caption:=SFrom; //Процесс;
if ilProcIcons<>nil then
ImageIndex:=ImageList_AddIcon(ilProcIcons.Handle, icon.handle);
end;
finally
icon.free;
MYFStream.Free;
end;
end;

Так вот если NMStrm передает слишком шустро то NMStrm дает ошибки передачи.
Если не слишком то все нормально.
В каком направлении двигаться, что сделать по другому?



Digitman   (2001-11-02 11:02) [9]

Двигаться нужно вот куда : почитать лителатуру по протоколу TCP и понять различия между stream-oriented (TCP) и message-oriented (UDP) соединениям.
TNMStrm/TNMStrmServ используют поточный (stream-oriented) режим транспорта пакетов. Это означает, что при возникновении события TSE.NMStrmServ1MSG поток, переданный параметром strm, вопреки твоим ожиданиям, содержит просто очередной блок данных, полученных от клиента, и его никак нельзя ассоциировать с данными, размер которых точно соответствует размеру отдельно переданной "картинки".
Для того, чтобы сервер мог прочитать ровно столько данных, сколько реально требуется для построения очередной ожидаемой "картинки", он должен знать размер данных, соответствующих очередной картинке в непрерывном потоке картинок, передаваемых клиентом. А как ему узнать этот размер ? Да никак он этого не узнает, если клиент сам ему об этом не сообщит !
Стандартное решение :
- клиент непосредственно перед передачей серверу собственно данных "картинки" передает ему некий служебный блок данных, содержащий инф-цию о размере следом передаваемых данных, соответствующих отдельной картинке.
- сервер в обработчике сообщения сначала читает эту инф-цию, а уж затем использует полученный размер для выборки из вх.потока-параметра блока данных, размер которого не больше заявленного клиентом; прием целой картинки может растянуться и на несколько событий, поэтому и нужна буферизация принятых блоков где-то в глобально (а не локально, как в твоем коде !) созданном потоке-буфере.



Kuzmin_Alex   (2001-11-03 17:58) [10]

Ты неправ. Ты все правильно написал, но это уже все сделано создателями компонент FastNet. Событие OnMsg возникает один раз когда отправленные данные уже собраны. Значит для их обработки вполне подходит и локальный буфер. А тот кто выше писал, что для каждого соединения создается своя нить - прав на 100%. Тогда вроде все должно работать. Но если в момент , когда обрабатывается OnMsg потянуть мышом за заголовок окна и подвигать его туда суда начинают лесть Exception. Может отказаться от NMstrm и NMServer в пользу стандартного Socket или еше чего нибудь попробовать?



Basaev   (2001-11-04 04:42) [11]

Удалено модератором



Digitman   (2001-11-05 08:50) [12]

>Kuzmin_Alex
"для каждого соединения создается своя нить"...
Это ты о NMServer ? Ну и что здесь удивительного ? Разумеется, любой классический сервер, поддерживающий технологию SuperServer, просто обязан обрабатывать каждый отдельный клиентский коннект в отдельном потоке. К твоей-то проблеме это какое отношение имеет ?
Если уж ты сомневаешься, в каком потоке возбуждается событие OnMsg, вставь в обработчик простую проверку
if GetCurrentThreadId <> MainThreadId then
... доп.поток
else
... осн.поток

"начинают лесть Exception"...
Так ведь, если ты не в состоянии разобраться, что за исключения возникают при использовании FastNet-компонентов, то и "стандартный Socket" тебе тоже не поможет ! Это уже проблемы, связанные с навыками отладки и трассировки собственного кода.



Kuzmin_Alex   (2001-11-08 21:33) [13]

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



Anatoly Podgoretsky   (2001-11-08 22:15) [14]

Ты хочешь услышать как тебе нравится или как надо.
Так останешься в тишине, один одинешенек со своими вопросами.
Не нравятся ответы, не читай и не реагируй.



Digitman   (2001-11-09 08:52) [15]

>Kuzmin_Alex



1."..потянуть мышом за заголовок окна и подвигать его туда суда начинают лесть Exception.." - КАКИЕ ?????????

2."Событие OnMsg возникает один раз когда отправленные данные уже собраны. Значит для их обработки вполне подходит и локальный буфер" - ну, пусть так, согласен. NMStrmServ сам делает буферизацию, собирая пакеты одного контекста в принятый поток.

Но ! Где связь между (1) и (2) ? Где твой анализ Exception ? Ты трассировал OnMsg() ?



Kuzmin_Alex   (2001-11-12 23:16) [16]

Ok.Больше не дерзю.
Что касается Exception, то вот оно с описанием:
WSAEISCONN (10056) Socket is already connected.
A connect request was made on an already connected socket. Some implementations also return this error if sendto is called on a connected SOCK_DGRAM socket (For SOCK_STREAM sockets, the to parameter in sendto is ignored), although other implementations treat this as a legal occurrence.
(За литературный перевод буду признателен).
А вот связь между перерисовкой окна и already connected я хотел бы узнать + как с этим бороться.




Форум: "Сети";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.02.04;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.76 MB
Время: 0.021 c
1-8936            Yuraz                 2002-01-03 08:49  2002.02.04  
Люди, подскажите, как слева в Code Explorer сделать нумерацию строк программного кода?


6-8970            Oplg                  2001-11-12 18:57  2002.02.04  
Вопрос


4-9038            Artis                 2001-12-09 13:24  2002.02.04  
Как узнать размер файла?


1-8862            Eraser                2002-01-21 12:34  2002.02.04  
Процедура Delay


1-8858            Chak                  2002-01-19 15:48  2002.02.04  
Как убить DLL-ку, находящуюся в памяти?