Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2003.02.27;
Скачать: [xml.tar.bz2];

Вниз

Socket ы. Передача строк.   Найти похожие ветки 

 
Fredericco   (2003-01-10 11:42) [0]

Привет уважаемые мастера!
Сложилась вот такая вот ситуация:
клиентом передаю данные в цикле 100 раз строку из 3351 символов:

s:=StringOfChar("T",3344);
DelMe:=0;
for i:=1 to 100 do begin
SendTextToServ(s);
Application.ProcessMessages;
// Sleep(50);
end;

..........
const
sCut:string="<-~!~->";
..........
procedure TForm1.SendTextToServ(Text:String);
begin
csDrv.Socket.SendText(Text+sCut);
Memo1.Lines.Add(IntToStr(Length(Text+sCut)));
DelMe:=DelMe+Length(Text+sCut);
Caption:=IntToStr(DelMe);
end;



принимаю так:

procedure TForm1.ssDrvClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
sh,sp:integer;
s:string;
begin
sh:=Socket.SocketHandle;
s:=Socket.ReceiveText;
sp:=Socket.LocalPort;
Memo2.Lines.Add(IntToStr(Length(s)));
DelMe:=DelMe+Length(s);
Label6.Caption:=IntToStr(DelMe);
end;



Если клиент отправляет с задержкой в 50 мс, то все правильно 335100 отправлено и ровно столько же получено, а если задержку убрать, то отправляется правильно, а принимается всегда по-разному, но в пределах от 30000 до 55000! При единичных небольших отправках все - ок, если отправляю сразу строку из 335100 символов - тоже все ок.
Не поможите ли мне в сложившейся ситуации?

Заранее благодарен
с уважением
Fredericco.


 
F1   (2003-01-10 11:53) [1]

А кто будет анализировать результат sendtext???
Он вель может не все послать, если буфер забит до отказа!!!
Посмотри событие OnWrite...


 
Fredericco   (2003-01-10 12:15) [2]

2 F1 © (10.01.03 11:53)
Спасибо, но я не очень понимаю как мне использовать OnWrite.
Не мог бы ты мне поподробнее рассказать, если не трудно, или ссылочку кинуть, гду поискать?


 
Digitman   (2003-01-10 12:46) [3]

Use SendText to write a string to the socket connection. The writing may occur in the OnSocketEvent event handler of a Windows socket object or in the OnWrite or OnClientWrite event handler of a socket component. Alternately, SendText may write from a socket that is expected to write to the connection without a notification to signal the connection’s readiness to read. If an error occurs while writing to the connection, SendText terminates the connection and raises an ESocketError exception.

SendText returns 0 if the string was successfully written. It returns a nonzero value if the writing must be postponed. When SendText returns a nonzero value, it must be called again later to write the value over the connection.



For non-blocking sockets, the data is sent to the WinSock DLL which has it"s own internal buffers. If the WinSock can accept additional data, SendBuf returns immediately with the number of bytes queued. If the WinSock internal buffer space is not able to accept the buffer being sent, SendBuf returns -1 and no data is queued at all. In this case, wait a bit for the WinSock to have a chance to send out already-queued data; then try again.


function TCustomWinSocket.SendText(const s: string): Integer;
begin
Result := SendBuf(Pointer(S)^, Length(S));
end;


For blocking sockets, SendBuf returns the number of bytes actually written.

Что здесь непонятного ?


 
Fredericco   (2003-01-10 12:56) [4]

2 Digitman © (10.01.03 12:46)
При всем моем уважении к тебе, я чего-то не понимаю

Writes the string S to the socket connection.

procedure SendText(const S: string);

Description

Use SendText to write a string to the socket connection. The writing may occur in the OnSocketEvent event handler of a Windows socket object or in the OnWrite or OnClientWrite event handler of a socket component. Alternately, SendText may write from a socket that is expected to write to the connection without a notification to signal the connection’s readiness to read. If an error occurs while writing to the connection, SendText terminates the connection and raises an ESocketError exception.

Извени, если я туплю :-)


 
Digitman   (2003-01-10 13:04) [5]

Нет, ну а что тебе в этой цитате неясно ? Конкретно ?


 
Fredericco   (2003-01-10 13:09) [6]

То, что у меня не функция, а

procedure TCustomWinSocket.SendText(const s: string);
begin
SendBuf(Pointer(S)^, Length(S));
end;

Пробывал менять в исходниках, на функцию, но ничего не поменялось, такое ощущение что ScktComp вообще не компилится, т.к. я в этом файле специально ошибку синтаксическую делаю, а компилятор ничего не видит....


 
Digitman   (2003-01-10 13:22) [7]

а-а-а !

Что-то я сразу не обратил внимание)

Чтобы перекомпилить, удали/переименуй DCU и подключи ScktComp.pas - модуль непосредственно к проекту.

Но - не советую этого делать.

Лучше пользуй SendBuf(). Я думаю, уж это-то - функция в D4 ?


 
Fredericco   (2003-01-10 13:29) [8]

Digitman © (10.01.03 13:22)
:-)
Есть.
Но тогда, если я правильно понял хелп, мне придется перевести клиента в режим ctBlocking? Это ни чем не черевато? Не придется ли что-либо менять? Да, и спасибо за помощь!


 
Digitman   (2003-01-10 13:36) [9]


> если я правильно понял хелп, мне придется перевести клиента
> в режим ctBlocking


Где это написано ? Такое обяз.требование ? Процитируй.


 
Fredericco   (2003-01-10 13:55) [10]

Digitman © (10.01.03 13:36)
Нигде :-). Не там смотрел, не так понял.
Но у меня снова проблемы, отправляю так:

tmp:=Text+sCut;
i:=csDrv.Socket.SendBuf(tmp,Length(tmp));
Memo1.Lines.Add(IntToStr(i));

Когда tmp равно до 3153 символа то это значение мне в i и возвращается, а при превышении этого значения - в Мемо вообще ничего не добавляется ни 0 ни -1 ни мосор какой-нибудь, но комп и прога не висят...


 
Fredericco   (2003-01-10 14:30) [11]

Ничего не происходило потому, что у меня в OnClientError Abort стояло. А так ошибка ESocketError 10022 on API send.


 
Digitman   (2003-01-10 14:36) [12]

Как это "не добавляется" ? Быть того не может)
Если строчка Memo1.Lines.Add(IntToStr(i)) выполнилась в принципе, то хоть что-то, но будет "добавлено" !

Это - раз.

Второе.

Result := SendBuf(Pointer(S)^, Length(S)); //оригинал Борланда
i:=csDrv.Socket.SendBuf(tmp,Length(tmp)); //твое "творчество"

Ты разницу-то вообще видишь ? В способе передачи 1-го (строкового) аргумента в ф-цию SendBuf() ?

Третье.

В non-blocking-режиме результат SendBuf() >=0 покажет тебе, сколько реально байт было помещено в буфер передачи гнезда. Если результат меньше затребованного к передаче числа байт, повторяй в цикле попытки передачи только тех байт, которые остались еще непереданными на данную итерацию цикла.

Если же non-blocking-режиме SendBuf() = -1, то - никаких циклов ! Запомни (где-либо) тек.позицию первого (из еще непереданных) байта данных в своем буфере и число байт, все еще требующих передачи. Как только возникнет событие OnWrite(), в его обработчике повтори попытку передачи тем же способом (передавая в SendBuf() параметрами запомненную ранее позицию и число байт)


 
Digitman   (2003-01-10 14:43) [13]


> у меня в OnClientError Abort стояло.


На основании чего у тебя Abort "стояло" ? От балды ? Чем руководствовался, размещая здесь этот оператор ?



 
Fredericco   (2003-01-10 14:45) [14]

У меня клиент по таймеру подключается в случае отсутствия коннекта (то есть сервера). Это я вместо ErrorCode:=0 использовал.


 
Digitman   (2003-01-10 14:49) [15]


> У меня клиент по таймеру подключается в случае отсутствия
> коннекта


Если речь - о клиенте, то почему OnClientError() ? Нет такого события у TClientSocket. А есть OnError().


> Это я вместо ErrorCode:=0 использовал.


Зачем ? ты вообще представляешь, как рабортает оператор Abort ? И аочему именно Abort ? От балды ? Или как-то обосновать можешь ?


 
Fredericco   (2003-01-10 15:43) [16]

Нет обосновать не могу. Но не от балды, в книжке давно читал, что-то типа тихая искл. ситуация. OnClientError - опечатолся. Сорри. А что Аборт нельзя делать?


 
Digitman   (2003-01-10 16:07) [17]

Ну тебе ж черным по белому пишут станд.логику обработки таких событий ! Чего выдумывать-то ?

Occurs when the socket fails in making, using, or shutting down a connection.

property OnError: TSocketErrorEvent;

Description

Write an OnError event handler to respond to errors that arise with the socket connection. Set the ErrorCode parameter to 0 if the OnError event handler successfully deals with the error condition, to prevent an ESocketError from being raised.

Не хочешь исключений ? Установи в обработчике ErrorCode - и всех делов. Др.вопрос, что кроме этого (в ряде случаев, связанных с ошибками типа WSAECONNREFUSED при попытке коннекта) в OnError() следует выполнять еще и Socket.Disconnect(Socket.SocketHandle) во избежание утечки WinSock-ресурсов и дабы не схлопотать по сему поводу WSAENOBUFS

Но у тебя-то - WSAEINVAL ! Совершенно жуткий случай для клиента) Ибо клиент явно bind не выполняет, а отказ этот говорит именно об этом :

The socket has not been bound with bind, or an unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled.

явно же bind выполняется только в коде TServerSocket (при переводе его в актив.состояние), из чего следует, что ошибку-то WSAEINVAL генерирует у тебя вовсе не TClientSocket)

А чего уж там ты на серверной части "наворотил" - одному господу известно)))


 
Fredericco   (2003-01-10 16:36) [18]

Digitman © (10.01.03 16:07)
Да я знаю, что дурак.
Короче у меня получилось. Можно я тебе расскажу, как я все это дело понял, а ты поправишь, если ошибаюсь?

Методом SendBuf мы просим сокет отправить данные такой-то длины. Сокет, в свою очередь, возвращает нам реальное положение дел, а именно:
. число большее -1, количество реально отправленных байт (если их меньше чем нам нужно пробуем отправить еще столько, сколько не отправили и так далее до тех пор пока все не отправим)
. -1, если его буфер полный и сокет не готов сейчас принять данные на передачу, а когда будет готов сообщит нам через событие OnWrite (мы же в OnWrite отправляем то, что не получилось)

Понятно, что терминология у меня хромает, но, все таки, суть верна?


 
Digitman   (2003-01-10 16:48) [19]

да, именно для non-blocking-режима - совершенно верно представляешь себе


 
Fredericco   (2003-01-10 16:53) [20]

Извини, что досаждаю, а зачем нужен этот blocking режим?


 
Digitman   (2003-01-10 17:19) [21]

его как правило используют для реализации гнездового транспорта в доп.код.потоках


 
Verg   (2003-01-11 12:43) [22]

Мне всегда был непонятен "тайный" смысл ReceiveText...
Какой текст? Сколько текст? На каком языке текст?... and so on...
Заглянул тут в реализацию

function TCustomWinSocket.ReceiveText: string;
begin
SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));
ReceiveBuf(Pointer(Result)^, Length(Result));
end;

И,.. ахренел....
Так это ж, просто, прием байтикофф по количеству сколько сокет принял за один раз...
Так кто ж сказал-то, сокет принамает за ОДИН раз все, что было послано ему оппонентом?
А фрагментация, а окна TCP, а прочя дурь?
Вот и "решение" - подождем 50 мс.-"подождё-ём, Твою Мать"
А слабо OnRead?



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

Форум: "Сети";
Текущий архив: 2003.02.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.008 c
14-87639
Pingo
2003-02-07 18:41
2003.02.27
M-Bus


3-87261
Ich Hasse
2003-02-07 23:25
2003.02.27
Сортировка SQL запросом


14-87618
Val
2003-02-07 19:09
2003.02.27
Передача графики на мобильник via e-mail


4-87764
Лёха2003
2003-01-10 23:38
2003.02.27
Дескрипторы окон в таскбаре


7-87733
zx
2002-12-26 17:51
2003.02.27
Звук на спикер?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский