Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Приём сообщений от сервера [D6, Win95/98, WinME, NT4, Win2k, WinXP]


Страницы:   1 2 3 4 5

Andr-04 ©   (2006-07-31 15:12:00) 

Добрый день. Как обойтись без использования WSAAsyncSelect для отправления сообщений от сервера и их приёма КЛИЕНТОМ?


Ketmar   (2006-08-03 18:37:00) [21]

мда. со ссылкой я лажанулся. она уже была. тогда таки советую ещё раз 5 прочитать статью...


Andr-04   (2006-08-03 18:15:00) [22]

Пишу не с компьютера, поэтому без цитат. Ура! ioctlsocket помог! Про ссылку я уже писал в 36 посте. Кстати, я читал обе статьи по тому адресу! Но про fd_close там, вроде, ничего нету. Хотя, может, я не заметил. По поводу блокирующего режима по умолчанию - в доке  по указанной выше ссылке было сказано, что сокеты, полученные в результате accept, наследуют параметры от слушаешего.


Ketmar   (2006-08-03 17:33:00) [23]

> [64] Сергей М. ©   (03.08.06 17:24)

ну да. и на буржуйском читать не надо было...
хотя, вот тут, например: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1021&mode=printесть ведь отличная статья по сокетам, и вся почти на русском. но гугль -- это табу, наверное...


Сергей М.   (2006-08-03 17:24:00) [24]


> Ketmar


Да так и есть, судя по всему)

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


Ketmar   (2006-08-03 17:21:00) [25]

мне это всё напоминает исследования какого-то внеземного аппарата "среденеумным" человеком. "а если мы тут покрутим? а если сюда нажмём? а если... ##%#%^#! Серёга, что это так бахнуло-то, @##^^@?!!!"
%-)


Сергей М.   (2006-08-03 17:09:00) [26]


> Andr-04   (03.08.06 17:03) [60]


О боже !)

Галиматьища-отсебячина, достойная картины маслом)


Сергей М.   (2006-08-03 17:08:00) [27]


> Andr-04   (03.08.06 17:01) [59]



> если тогда сокеты, создающиеся для каждого подключения,
> переводить в блокирующий режим при помощи IOCtlSocket(sock,
>  FIONBIO, i);, где i:=0?


Нахрена их куда-то "переводить", если по умолчанию они и так создаются блокирующими ?

Документацию, в конце-концов, будем читать или нет ? Что ты тут клоунаду-то устраиваешь ?


> пытаюсь понять смысл написанного на буржуйском. Увы, английский
> пока хромает


Что , не хватает уже смелости задать "по чесноку" вопрос "переведите мне на руссиш такую-то буржуйскую фразу" ?

Что ж ты так обмельчал-то, не повзрослев))...


Andr-04   (2006-08-03 17:03:00) [28]

OK, попробую поставить тогда в FD_CLOSE проверку при помощи ioctlsocket(wParam, FIONREAD, l);


Andr-04   (2006-08-03 17:01:00) [29]

> При этом режим всех гнезд у него неблокирующий ? Неблокирующий.
> Значит не исключены переполнения буферов передачи.
> Значит необходимо контролировать события их освобождения,
>  прежде чем повторять попытки записи в эти буферы. На то
> FD_WRITE и существует.

Сейчас у меня сразу закрывается соединение в подобном случае. А если тогда сокеты, создающиеся для каждого подключения, переводить в блокирующий режим при помощи IOCtlSocket(sock, FIONBIO, i);, где i:=0? Ладно, подкорректирую чуть позже - возни много.

А приумолк потому, что всё пытаюсь понять смысл написанного на буржуйском. Увы, английский пока хромает и значительного понимания написанного пока не получил. Пытаюсь... :-)


Сергей М.   (2006-08-03 16:16:00) [30]

Что приумолк-то, Кулибин ?)


Сергей М.   (2006-08-03 15:20:00) [31]


> смысл тогда какой от 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.


Andr-04   (2006-08-03 15:05:00) [32]

Я всё время хожу в kolTCPSocket.pas. Попробую ещё тогда и в scktcomp.pas.

> 4. При чем здесь клиент и его режим ? Сейчас речь идет о
> сервере и неблок.режиме !

Хорошо, смысл тогда какой от WD_WRITE? Что я должен там обрабатывать.

По поводу вопроса №2:
> но из WSAAsyncSelect для проверки убирал - тоже ни к чему
> не привело.


Из-за чего я получаю лишнее сообщение об отключении ДО ПОЛУЧЕНИЯ БУФЕРА?!


Сергей М.   (2006-08-03 14:27:00) [33]


> Andr-04   (03.08.06 14:11) [54]


1. Экспериментировать подобным образом следует лишь в случаях, когда соотв.момент либо не освещен либо слабо освещен в док-ции.

2.
> неожиданно прерывается отключение сервера?


Что за галиматья ?
Ты таки сходил в scktcomp.pas или по-прежнему упираешься ?)

3. Раз добавил  - уже хорошо). Это нормальнаяреакция на FD_CLOSE.

4. При чем здесь клиент и его режим ? Сейчас речь идет о сервере и неблок.режиме !


Andr-04   (2006-08-03 14:11:00) [34]

1. Да, здесь я ошибся, исправил. Сначала ради эксперемента поставил, а потом забыл убрать.
2. Почему? А если, напримаер, неожиданно прерывается отключение сервера? Если, например, сеть вырубилась? Я в процедуре disconnectall закрываю все сокеты, созданные при вызове accept, закрываю стреймы и удаляю эти элементы из динамического массива, т.е. в цикле посылаю сообщения о стандартном закрытии всех сокетов (через SendMessage). Скажу честно - на практике ещё проверить не успел (теоретически должно работать), но из WSAAsyncSelect для проверки убирал - тоже ни к чему не привело.
3. Добавил, хотя не уверен, что именно из-за этого получается ложное событие. Но замечание, действительно, верное.
4. А что это даёт? Разве только информацию о переполнении исходящего буфера и его освобождении... В моём случае клиент работает в блокирующем режиме и считывает необходимые данные сразу и в цикле записывает их с стрейм. Думаю, вероятность переполнения мала.

Исправил всё с учётом замечаний - результат нисколько не изменился! Клиент нужен?


Сергей М.   (2006-08-03 12:42:00) [35]

4. Где реакция на событие FD_WRITE ?


Сергей М.   (2006-08-03 12:41:00) [36]


> Здесь я всё сделал НОРМАЛЬНО


Здесь ты тоже нахреновертил, не читая внимательно документацию и не проанализировав исх-ки у самого Борланда)

1. в listen() следует задавать backlog-параметром константу SOMAXCONN.

2. Нет абсолютно никакого резона интересоваться событием FD_CLOSE у слушающего гнезда.

3. Где у тебя закрытие гнезда как реакция на FD_CLOSE ?


Andr-04   (2006-08-03 12:27:00) [37]


> Не могу только понять почему перед FD_READ происходит ЛИШНИЙ FD_CLOSE?! И ещё после FD_READ происходит...

А если программу отлаживать по шагам, то лишний FD_CLOSE не замечается. Я заметил, что лишний появляется если клиент сразу закрывает соединение после передачи данных. Если перед закрытием сделать паузу, то лишний FD_CLOSE не возникает.


Andr-04   (2006-08-03 12:21:00) [38]

Забыл убрать из var'а лишние переменные, не имеющие отношения к делу, одни из которых собственного типа.
WSAAsyncSelect ни причём потому что приём сообщений от сервера от неё не зависит.

> Или ты перевел гнездо в неблок.режим без нотификаций ? ТОгда
> откуда у тебя взялись FD-события ? Или ты обычный select
> пользуешь ?
>
> Да и не может быть у гнезда, которое было создано ф-цией
> accept(), события FD_ACCEPT - оно специфично лишь для слушающего
> гнезда.

Здесь я всё сделал НОРМАЛЬНО - см. код. Не могу только понять почему перед FD_READ происходит ЛИШНИЙ FD_CLOSE?! И ещё после FD_READ происходит...


Andr-04   (2006-08-03 12:13:00) [39]

Вернее, 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;


Сергей М.   (2006-08-03 12:13:00) [40]


> В блокирующий режим переводить - не помогает


Ты же сказал, что WSAAsyncSelect ни при чем ?!
Значит, у тебя и так уже блокирующий режим используется)
Или ты перевел гнездо в неблок.режим без нотификаций ? ТОгда откуда у тебя взялись FD-события ? Или ты обычный select пользуешь ?

Да и не может быть у гнезда, которое было создано ф-цией accept(), события FD_ACCEPT - оно специфично лишь для слушающего гнезда.


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо