Текущий архив: 2006.12.24;
Скачать: CL | DM;
Вниз
Приём сообщений от сервера Найти похожие ветки
← →
Сергей М. © (2006-08-02 15:41) [40]
> medved_68 © (02.08.06 15:12) [38]
> ты точно гонишь
"Эт точно" (с) Сухов
← →
Andr-04 (2006-08-03 11:06) [41]Не гоню! Правда, первый год это был Паскаль, потом чистый VCL, BDE и вся стандартная ерунда. А последние 2,5 года пишу исключительно в KOL, что часто приводит к рассмотрению и WinAPI. Вот и хорошо. Это с сокетами я тольо так лопухнулся! Если так хотите посмотреть на мой проек - пишите мыло, а если не верите - ну и не надо! Мне от этого ни горячо, ни холодно.
А WSAAsyncSelect, как оказалось, здесь действительно не причём.
← →
Andr-04 (2006-08-03 11:13) [42]Да и динимаическими массивами только годик с лишнима занимаюсь... Ну не было необходимости, вот и не знал! Шесть лет для программирования может показаться большим сроком, если шесть лет исследовать каждую его область. Я же этим занимаюсь не на протяжении всего периода, да и нет так усердно, честно говоря. Изучаю только то, что требуется в данный момент.
← →
Andr-04 (2006-08-03 11:16) [43]Что-то обсуждений моей личности здесь слишком много. А ведь для этого, вроде, есть специальное место (вроде - это потому, что я там никогда не был).
← →
Ketmar © (2006-08-03 11:18) [44]> [42] Andr-04 (03.08.06 11:13)
> годик с лишним
бросайте Вы, благородный дон, это программирование. коли за "годик с лишним" не смогли разобраться с динамическими массивами, то не попробовать ли Вам занятие попроще?
← →
Сергей М. © (2006-08-03 11:22) [45]
> Andr-04 (03.08.06 11:13) [42]
> не было необходимости, вот и не знал
А тут вдруг появилась, надо понимать ?
Подозреваю, что ты пытаешься приспособить для аккумуляции принимаемых данных. А разумней для этой цели было бы использовать стрим, а не массив.
← →
Andr-04 (2006-08-03 11:42) [46]Динамические массивы не было необходимости никуда передавать! Я их до этого случая использовал для хранения переменных данных, всего навсего. Например, для хранения указателей (PControl) на динамические компоненты и т.п. (Конечно, в KOL все они динамические - я имею в виду те, которые я создавал сам в процессе работы программы, а не те, которые пишет MCK при компиляции).
Да, Вы правы. Я всё записывал ещё и в стрим. Провернул всё в голове и послал пока этот динамический куда подальше! При приёме буфера записываю сначала всё в статический массив, а потом в стрим.
Поскольку обсуждение ещё не закрыли, позволю задать ещё вопрос: почему при подключении, передаче данных и отключении клиента сначала срабатывает FD_ACCEPT, потом FD_CLOSE и лишь после этого FD_READ? Как поменять FD_CLOSE местами с FD_READ? Это же физически невозможно передавать буфер с закрытым сокетом! В блокирующий режим переводить - не помогает. Ато это приводит к уничтожению Stream"а (у меня - при вызове FD_CLOSE). Если через отладку всё делать, то всё происходит как положено.
← →
Сергей М. © (2006-08-03 11:50) [47]
> почему при подключении, передаче данных и отключении клиента
> сначала срабатывает FD_ACCEPT, потом FD_CLOSE и лишь после
> этого FD_READ?
Быть того не может)
Показывай код сервера ..
← →
Сергей М. © (2006-08-03 12:13) [48]
> В блокирующий режим переводить - не помогает
Ты же сказал, что WSAAsyncSelect ни при чем ?!
Значит, у тебя и так уже блокирующий режим используется)
Или ты перевел гнездо в неблок.режим без нотификаций ? ТОгда откуда у тебя взялись FD-события ? Или ты обычный select пользуешь ?
Да и не может быть у гнезда, которое было создано ф-цией accept(), события FD_ACCEPT - оно специфично лишь для слушающего гнезда.
← →
Andr-04 (2006-08-03 12:13) [49]Вернее, FD_CLOSE ещё раз после FD_READ срабатывает.
Создаю сервер так:srvhnd:=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if not errortest(srvhnd) then
begin
with adr do
begin
sin_family:=AF_INET;
sin_port:=htons(srvport);
integer(sin_addr):=INADDR_ANY;
end;
if errortest(bind(srvhnd, adr, sizeof(adr))) then
begin
closesocket(srvhnd);
srvhnd:=0;
end
else
begin
wsaasyncselect(srvhnd, srvwnd, WIN_SOCKET, FD_ACCEPT or FD_CLOSE);
if errortest(winsock.listen(srvhnd, 65535)) then
begin
closesocket(srvhnd);
srvhnd:=0;
end;
end;
end
else
srvhnd:=0;
А вот обработка сообщений:function WindowProc(wnd: HWND; Msg: Integer; Wparam: Wparam; Lparam: Lparam): Lresult; stdcall;
var
s: String;
p, si: PStream;
c, crc, st: Cardinal;
cl: TClient;
b: byte;
w: word;
err: boolean;
i, j, k, l: Integer;
adr: TSockAddr;
sock: TSocket;
buf: array [0..8191] of byte;
begin
case msg of
WIN_SOCKET:
if hiword(lparam)<=WSABASEERR then
case loword(lparam) of
FD_ACCEPT:
begin
l:=sizeof(adr);
sock:=accept(srvhnd, @adr, @l);
if not errortest(sock) then
begin
wsaasyncselect(sock, srvhnd, WIN_SOCKET, FD_READ or FD_CLOSE);
setlength(indata, length(indata)+1);
indata[length(indata)-1].SockHandle:=sock;
indata[length(indata)-1].Stream:=NewMemoryStream;
indata[length(indata)-1].IPAddr:=inet_ntoa(adr.sin_addr);
indata[length(indata)-1].CmdSize:=0;
end;
end;
FD_READ:
begin
l:=recv(wParam, buf, sizeof(buf), 0);
i:=IndexOfSock(wParam);
if (l>0) and (i>-1) then
//обработка полученных данных
end;
FD_CLOSE:
if wparam=srvhnd then
disconnectall
else
begin
i:=IndexOfSock(wParam);
if i>-1 then
begin
CloseMemStream(indata[i].Stream);
delindata(indata, i);
end;
end;
end;
else
Result:=DefWindowProc(wnd, msg, wparam, lparam);
end;
end;
← →
Andr-04 (2006-08-03 12:21) [50]Забыл убрать из var"а лишние переменные, не имеющие отношения к делу, одни из которых собственного типа.
WSAAsyncSelect ни причём потому что приём сообщений от сервера от неё не зависит.
> Или ты перевел гнездо в неблок.режим без нотификаций ? ТОгда
> откуда у тебя взялись FD-события ? Или ты обычный select
> пользуешь ?
>
> Да и не может быть у гнезда, которое было создано ф-цией
> accept(), события FD_ACCEPT - оно специфично лишь для слушающего
> гнезда.
Здесь я всё сделал НОРМАЛЬНО - см. код. Не могу только понять почему перед FD_READ происходит ЛИШНИЙ FD_CLOSE?! И ещё после FD_READ происходит...
← →
Andr-04 (2006-08-03 12:27) [51]
> Не могу только понять почему перед FD_READ происходит ЛИШНИЙ FD_CLOSE?! И ещё после FD_READ происходит...
А если программу отлаживать по шагам, то лишний FD_CLOSE не замечается. Я заметил, что лишний появляется если клиент сразу закрывает соединение после передачи данных. Если перед закрытием сделать паузу, то лишний FD_CLOSE не возникает.
← →
Сергей М. © (2006-08-03 12:41) [52]
> Здесь я всё сделал НОРМАЛЬНО
Здесь ты тоже нахреновертил, не читая внимательно документацию и не проанализировав исх-ки у самого Борланда)
1. в listen() следует задавать backlog-параметром константу SOMAXCONN.
2. Нет абсолютно никакого резона интересоваться событием FD_CLOSE у слушающего гнезда.
3. Где у тебя закрытие гнезда как реакция на FD_CLOSE ?
← →
Сергей М. © (2006-08-03 12:42) [53]4. Где реакция на событие FD_WRITE ?
← →
Andr-04 (2006-08-03 14:11) [54]1. Да, здесь я ошибся, исправил. Сначала ради эксперемента поставил, а потом забыл убрать.
2. Почему? А если, напримаер, неожиданно прерывается отключение сервера? Если, например, сеть вырубилась? Я в процедуре disconnectall закрываю все сокеты, созданные при вызове accept, закрываю стреймы и удаляю эти элементы из динамического массива, т.е. в цикле посылаю сообщения о стандартном закрытии всех сокетов (через SendMessage). Скажу честно - на практике ещё проверить не успел (теоретически должно работать), но из WSAAsyncSelect для проверки убирал - тоже ни к чему не привело.
3. Добавил, хотя не уверен, что именно из-за этого получается ложное событие. Но замечание, действительно, верное.
4. А что это даёт? Разве только информацию о переполнении исходящего буфера и его освобождении... В моём случае клиент работает в блокирующем режиме и считывает необходимые данные сразу и в цикле записывает их с стрейм. Думаю, вероятность переполнения мала.
Исправил всё с учётом замечаний - результат нисколько не изменился! Клиент нужен?
← →
Сергей М. © (2006-08-03 14:27) [55]
> Andr-04 (03.08.06 14:11) [54]
1. Экспериментировать подобным образом следует лишь в случаях, когда соотв.момент либо не освещен либо слабо освещен в док-ции.
2.
> неожиданно прерывается отключение сервера?
Что за галиматья ?
Ты таки сходил в scktcomp.pas или по-прежнему упираешься ?)
3. Раз добавил - уже хорошо). Это нормальная реакция на FD_CLOSE.
4. При чем здесь клиент и его режим ? Сейчас речь идет о сервере и неблок.режиме !
← →
Andr-04 (2006-08-03 15:05) [56]Я всё время хожу в kolTCPSocket.pas. Попробую ещё тогда и в scktcomp.pas.
> 4. При чем здесь клиент и его режим ? Сейчас речь идет о
> сервере и неблок.режиме !
Хорошо, смысл тогда какой от WD_WRITE? Что я должен там обрабатывать.
По поводу вопроса №2:
> но из WSAAsyncSelect для проверки убирал - тоже ни к чему
> не привело.
Из-за чего я получаю лишнее сообщение об отключении ДО ПОЛУЧЕНИЯ БУФЕРА?!
← →
Сергей М. © (2006-08-03 15:20) [57]
> смысл тогда какой от WD_WRITE? Что я должен там обрабатывать
Сервер у тебя что-то передает клиенту ? Передает.
При этом режим всех гнезд у него неблокирующий ? Неблокирующий.
Значит не исключены переполнения буферов передачи.
Значит необходимо контролировать события их освобождения, прежде чем повторять попытки записи в эти буферы. На то FD_WRITE и существует.
> Из-за чего я получаю лишнее сообщение об отключении
The FD_CLOSE message is posted when a close indication is received for the virtual circuit corresponding to the socket. In TCP terms, this means that the FD_CLOSE is posted when the connection goes into the TIME WAIT or CLOSE WAIT states. This results from the remote end performing a shutdown on the send side or a closesocket. FD_CLOSE should only be posted after all data is read from a socket, but an application should check for remaining data upon receipt of FD_CLOSE to avoid any possibility of losing data.
Please note your application will receive ONLY an FD_CLOSE message to indicate closure of a virtual circuit, and only when all the received data has been read if this is a graceful close. It will not receive an FD_READ message to indicate this condition.
← →
Сергей М. © (2006-08-03 16:16) [58]Что приумолк-то, Кулибин ?)
← →
Andr-04 (2006-08-03 17:01) [59]> При этом режим всех гнезд у него неблокирующий ? Неблокирующий.
> Значит не исключены переполнения буферов передачи.
> Значит необходимо контролировать события их освобождения,
> прежде чем повторять попытки записи в эти буферы. На то
> FD_WRITE и существует.
Сейчас у меня сразу закрывается соединение в подобном случае. А если тогда сокеты, создающиеся для каждого подключения, переводить в блокирующий режим при помощи IOCtlSocket(sock, FIONBIO, i);, где i:=0? Ладно, подкорректирую чуть позже - возни много.
А приумолк потому, что всё пытаюсь понять смысл написанного на буржуйском. Увы, английский пока хромает и значительного понимания написанного пока не получил. Пытаюсь... :-)
← →
Andr-04 (2006-08-03 17:03) [60]OK, попробую поставить тогда в FD_CLOSE проверку при помощи ioctlsocket(wParam, FIONREAD, l);
← →
Сергей М. © (2006-08-03 17:08) [61]
> Andr-04 (03.08.06 17:01) [59]
> если тогда сокеты, создающиеся для каждого подключения,
> переводить в блокирующий режим при помощи IOCtlSocket(sock,
> FIONBIO, i);, где i:=0?
Нахрена их куда-то "переводить", если по умолчанию они и так создаются блокирующими ?
Документацию, в конце-концов, будем читать или нет ? Что ты тут клоунаду-то устраиваешь ?
> пытаюсь понять смысл написанного на буржуйском. Увы, английский
> пока хромает
Что , не хватает уже смелости задать "по чесноку" вопрос "переведите мне на руссиш такую-то буржуйскую фразу" ?
Что ж ты так обмельчал-то, не повзрослев))...
← →
Сергей М. © (2006-08-03 17:09) [62]
> Andr-04 (03.08.06 17:03) [60]
О боже !)
Галиматьища-отсебячина, достойная картины маслом)
← →
Ketmar © (2006-08-03 17:21) [63]мне это всё напоминает исследования какого-то внеземного аппарата "среденеумным" человеком. "а если мы тут покрутим? а если сюда нажмём? а если... ##%#%^#! Серёга, что это так бахнуло-то, @##^^@?!!!"
%-)
← →
Сергей М. © (2006-08-03 17:24) [64]
> Ketmar
Да так и есть, судя по всему)
Кулибину, ему проще было - он не знал ни про какие "внеземные" дела, хотя, согласись, был далеко не "среднеумным")
← →
Ketmar © (2006-08-03 17:33) [65]> [64] Сергей М. © (03.08.06 17:24)
ну да. и на буржуйском читать не надо было...
хотя, вот тут, например: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1021&mode=print есть ведь отличная статья по сокетам, и вся почти на русском. но гугль -- это табу, наверное...
← →
Andr-04 (2006-08-03 18:15) [66]Пишу не с компьютера, поэтому без цитат. Ура! ioctlsocket помог! Про ссылку я уже писал в 36 посте. Кстати, я читал обе статьи по тому адресу! Но про fd_close там, вроде, ничего нету. Хотя, может, я не заметил. По поводу блокирующего режима по умолчанию - в доке по указанной выше ссылке было сказано, что сокеты, полученные в результате accept, наследуют параметры от слушаешего.
← →
Ketmar © (2006-08-03 18:37) [67]мда. со ссылкой я лажанулся. она уже была. тогда таки советую ещё раз 5 прочитать статью...
← →
Andr-04 (2006-08-03 19:02) [68]Почитаю при необходимости. Уж с этим я сам как-нибудь разберусь. А вам всем советую быть по-вежливее!
← →
Andr-04 (2006-08-03 19:02) [69]Почитаю при необходимости. Уж с этим я сам как-нибудь разберусь. А вам всем советую быть по-вежливее!
← →
Ketmar © (2006-08-03 19:26) [70]ай. снова гуру пришёл...
← →
Andr-04 (2006-08-03 20:05) [71]Само по себе слово Гуру не оскорбительное, но здесь оно звучит унизительно. Да я, собственно, никуда и не уходил! Может, всё-таки, прикратим разборки и засирание форума? Или модерам всё по...
← →
FireMan_Alexey © (2006-08-03 23:24) [72]Так что ты конкретно пишешь?
Может подскажем как :)
Скажи что должно передаваться и что приниматься?
Если это очередной прокси...
← →
Andr-04 (2006-08-04 02:23) [73]Да нет, далеко не прокси!.. Пишу четырехлетний проект, в котором лишь присутствует управление по локальной сети, а сам проект вовсе не предназначен для масштабного взаимодействия с локальной сетью и Интернет. Правда ядро уже обновлено, ему 2,5 года... Сама тема проекта не представляет никакого интереса и масштабного использования, поэтому писать её название я умышленно не буду, однако методы решений, используемые в проекте, могут найти свое применение не мало где ещё. Ну для прокси там, конечно, маловато чего можно найти, а вот для использования файлов чужого компьютера, например, - в самый раз. Перед созданием этой темы форума велась работа по созданию сетевых стреймов для KOL"а... Сейчас, благодаря этому форуму, работа с ними практически закончена (осталось только разобраться с исходящим буфером по рекомендации Сергея М. - пока ещё думаю, стоит ли эта игра свеч, т.к. изменять придется немало, потому что сервер работает в режиме "вопрос-ответ", а тут ответ нужно будет ещё кэшировать, да и когда этот FD_WRITE не происходит из документации толком не понял). Это что касается сетевой части. Помимо этого ещё присутствуют собственная, независимая от стороннего ПО, шифруемая БД и другие мелочи. Вообще, первоначально ставилась другая цель разработки данного проекта, но теперь он превратился в средство воплащения идей и развивается только при наличии свободного времени, а также при возникновении ситуации, которая и вдохновила меня на создание проекта. Если есть желание посмотреть на проект, может и баги поискать - подтвердите это и, при необходимости, оставьте e-mail - и я его вышлю. Правда, вышлю не новую версию (без сетевых стреймамов и прочих запланированных функций - эта версия ещё в стадии разработки) и БЕЗ ИСХОДНИКОВ! Но шифрование БД в ней присутствует (оно появилось с появлением нового ядра программы).
← →
Сергей М. © (2006-08-04 08:57) [74]
> Andr-04 (04.08.06 02:23) [73]
> когда этот FD_WRITE не происходит из документации толком
> не понял
FD_WRITE происходит как минимум однократно:
1. для кл.гнезда - сразу же за FD_CONNECT
2. для серв. гнезда, того что создается ф-цией accept - сразу после успешного его создания
FD_WRITE происходит всякий раз при фактическом освобождении буфера передачи, если предыдущий вызов ф-ции send() вернул отказ с кодом WSAEWOULDBLOCK, фиксирующий факт невозможности записи в буфер передачи данных размером более свободного места в этом буфере на этот момент.
По сути этот внутренний буфер передачи представляет собой очередь (FIFO), в хвост которой помещаются данные, указываемые при вызовах send-функций, и из головы которой по мере готовности транспортного канала выбираются данные для фактической передачи их в канал.
Буфер имеет фиксированный в каждый момент времени размер, который может быть определен вызовом GetSockOpt(SO_SNDBUF) и переопределен вызовом SetSockOpt(SO_SNDBUF). Буфер индивидуален для каждого гнезда и его размер по умолчанию равен 8К (зависит от ряда важных системных параметров).
При получении отказа с кодом WSAEWOULDBLOCK следует прекратить дальнейшие попытки вызовов send-ф-ций вплоть до возникновения события FD_WRITE.
← →
Ketmar © (2006-08-04 10:03) [75]> [73] Andr-04 (04.08.06 02:23)
"я вам вышлю то, не знаю что". хоть бы сказал сначала, что за проект-то. вдруг это телефонный справочник? исходя из "не представляет никакого интереса и масштабного использования", справочник вполне подходит.
← →
Andr-04 (2006-08-04 12:49) [76]По поводу FD_WRITE меня смущало предложение "Если же программа отправляет данные не очень большими порциями и относительно редко, не переполняя буфер, то второй раз событие FD_Write не возникнет никогда.". Теперь всё понял (как-то подчёркнутую фразу всё пропускал и, в итоге, боялся, что не получу извещения об освобождении буфера). За ночь в голове уже сформировался алгоритм работы (создам новый динамический массив стреймов для исходящего буфера и буду его заполнять и отправлять при поступлении FD_READ и доотправлять при FD_WRITE). По поводу программы - это и не телефонный справочник, если так интересно - это программа для проверки знаний.
← →
Сергей М. © (2006-08-04 12:59) [77]
> программа для проверки знаний
.. и она, конечно же, ни в коем случае не может использовать готовые компоненты - только на WinsockAPI и только через самоистязание такие программы пишутся)
← →
Andr-04 (2006-08-04 13:14) [78]Основная цель её написаниея - для себя, чтобы не сидеть на месте! Просто интересно было заглянуть немножечко поглубже в работу приложений, вот и пишу на WinSockAPI и другие API. А что толку использовать стандартные компоненты? Вероятность узнать что-то новое, в таком случае, понижается. Да и KOL только за такой подход! В этом сам убедился, когда в KOL.pas исправлял недоделки, руководствуясь всё тем же VCL. Знания не бывают лишними. Надеюсь, мои старания ещё мне пригодятся! ;-)
← →
Сергей М. © (2006-08-04 13:38) [79]
> что толку использовать стандартные компоненты?
> вероятность узнать что-то новое, в таком случае, понижается
Да неужели ?)
Ну хорошо, ну не хочешь ты использовать стандартные компоненты (и/или компоненты вообще), но то самое "новое" лежит прямо у тебя перед носом - в исходниках этих компонентов.. Работающих ! Трассируемых ! Дающих практически нахаляву бесценную инф-цию о правильном использовании API !
))
← →
Andr-04 (2006-08-04 13:44) [80]Когда могу разобраться в этих исходниках - так и делаю. На основе чего, Вы думаете, я SockStream свой написал?
Страницы: 1 2 3 вся ветка
Текущий архив: 2006.12.24;
Скачать: CL | DM;
Память: 0.67 MB
Время: 0.057 c