Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.12.24;
Скачать: CL | DM;

Вниз

Приём сообщений от сервера   Найти похожие ветки 

 
Andr-04   (2006-07-31 15:12) [0]

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


 
Сергей М. ©   (2006-07-31 15:29) [1]

Прямо так и обойтись - не используя WSAAsyncSelect.


 
Andr-04   (2006-07-31 15:30) [2]

Т.е. как клиенту принимать сообщения от сервера в блокирующем режиме? И, если нужно, что должен выполнить сервер перед самой функцией send? Спасибо.


 
Сергей М. ©   (2006-07-31 15:32) [3]


> как клиенту принимать сообщения от сервера в блокирующем
> режиме?


прямо так и принимать - recv()


> что должен выполнить сервер перед самой функцией send?


Ты со стула упал ?
Или не понимаешь , что такое "вопрос-ответ" при общении клиента с сервером ?


 
Andr-04   (2006-07-31 15:42) [4]

Нет, не получается. Перечислю ключевые вызовы процедур из своей программы:
<CODEvar
 fSocket: TSocket;
 fBufSize, sz: Integer;
 sa: TSockAddr;
begin
 fSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 if fSocket <> INVALID_SOCKET then
   begin
     FillChar(sa, SizeOf(TSockAddr), 0);
     sa.sin_family := AF_INET;
     sa.sin_port := htons(Port);
     sa.sin_addr.S_addr := inet_addr(PChar(IP));
     if connect(fSocket, sa, SizeOf(TSockAddr))>-1 then
       if listen(fSocket, SOMAXCONN)=0 then
         begin
           sz:=sizeOf(fBufSize);
           getsockopt(fSocket, SOL_SOCKET, SO_RCVBUF, PChar(@fBufSize), sz);
           sz:=send(fSocket, buf, sz, 0);
           ...
           sz:=recv(fSocket, buf[0], fBufSize, 0);
         end;
   end;
end;>
При описанном выше варианте sz, та, что возвращается после recv, всегда -1. Вот я и спрашиваю как это исправить?


 
Andr-04   (2006-07-31 15:48) [5]

Нет, не получается. Перечислю ключевые вызовы процедур из своей программы:
var
fSocket: TSocket;
fBufSize, sz: Integer;
sa: TSockAddr;
begin
fSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if fSocket <> INVALID_SOCKET then
  begin
    FillChar(sa, SizeOf(TSockAddr), 0);
    sa.sin_family := AF_INET;
    sa.sin_port := htons(Port);
    sa.sin_addr.S_addr := inet_addr(PChar(IP));
    if connect(fSocket, sa, SizeOf(TSockAddr))>-1 then
      if listen(fSocket, SOMAXCONN)=0 then
        begin
          sz:=sizeOf(fBufSize);
          getsockopt(fSocket, SOL_SOCKET, SO_RCVBUF, PChar(@fBufSize), sz);
          sz:=send(fSocket, buf, sz, 0);
          ...
          sz:=recv(fSocket, buf[0], fBufSize, 0);
        end;
  end;
end;

При описанном выше варианте sz, та, что возвращается после recv, всегда -1. Вот я и спрашиваю как это исправить?

Нет, со стула я не падал - просто мы посты [1] и [2] отправили почти в одно время, поэтому я и не успел прочитать Ваш ответ. Просто я с сокетами всегда только в блокирующем режиме работал, с организацией нескольких потоков. Сейчас всё равно исправлять буду на неблокирующий режим, но, всё-же, в одном месте моей программы лучше использовать блокирующий режим (там осуществлена работа без потоков и необходимо ожидание результата).


 
Ketmar ©   (2006-07-31 21:27) [6]

??? connect(), а потом listen()? или Вы с какими-то марсианскими сокетами работали, или странные очень мануалы курили...
есть подозрение, что остальной код "работы" примерно на том же уровне. я угадал?


 
DiamondShark ©   (2006-08-01 00:21) [7]


> connect(), а потом listen()?

технология клиент-сервер.


 
Andr-04   (2006-08-01 00:50) [8]

Не ругайте сильно! Если бы я знал что писать, то не спрашивал бы. Я никогда не сталкивался с необходимостью принимать сообщения от сервера. И что в этом такого страшного? Всё бывает когда-то первый раз! Если вас раздражают подобные вопросы - не пишите ответы. Со своей стороны я тоже пытаюсь найти ответ - ищу справочную литературу. Так оказалось, что сначала ничего найти не удавалось, поэтому, ради экономии времени, и задал вопрос здесь. Но ответа найти пока не удалось.


 
Сергей М. ©   (2006-08-01 08:11) [9]


> Andr-04   (01.08.06 00:50) [8]


listen() никогда не используется на стороне клиента, это ф-ция сервера.


 
Сергей М. ©   (2006-08-01 08:15) [10]


> Andr-04


В целм код ужасный.
Почитай book.itep.ru, разделы "Winsock" и "Протокол TCP", там есть красочная циклограмма, наглядно иллюстрирующая, какие ф-ции и в какой последовательности вызываются на стороне сервера и на стороне клиента и что при этом происходит в недрах протокола.


 
Ketmar ©   (2006-08-01 09:59) [11]

>DiamondShark ©   (01.08.06 00:21) [7]
Дим, это технология "а вот сколько всяких функция й знаю". %-)

>Andr-04   (01.08.06 00:50) [8]
что характерно (ц), нужные ответы есть в справке, идущей вместе с Delphi. надо только не лениться читать и думать.


 
Andr-04   (2006-08-01 14:52) [12]

Читаю, читаю... Говорил же уже! Правда, глаза сильно устают - принтер старый сломался, а шестерёнок нигде нету. А на счёт Listen - я её убирал - при отладке заметил, что ответ от неё -1, но это проблему не решило.


 
Сергей М. ©   (2006-08-01 15:03) [13]


> Andr-04   (01.08.06 14:52) [12]


Ну хорошо.
Предположим, огр.кучу док-ции в эл.виде действительно читать тяжело.

Но прочитать десяток-другой строк из справки к recv() вполне можно было !

Ведь там черным по белому написано (цитата из справки к recv):

Return Values

If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError

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


 
Ketmar ©   (2006-08-01 15:53) [14]

а можно пояснить глубокий эзотерический смысл вызова getsockopt()? или это опять из серии "а я в справке новую функцию нарыл"?

далее. очень интересно, что такое buf, какого оно размера, и почему в одном месте просто buf, а в другом -- buf[0]?

ну и: что, таки, возвращает WSAGetLastError(), как справедливо поинтересовался Сергей М.?


 
Andr-04   (2006-08-01 15:55) [15]

Я понял, что Listen не нужен и всё. А остальное всё оставил. Пока решил зрение напрягать. Может ещё за одно что узнаю, чем читать на английском описание каждой функции/процедуры.


 
Сергей М. ©   (2006-08-01 16:53) [16]


> Может ещё за одно что узнаю


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

Ибо ты никак не прореагировал на WSAGetLastError.


 
Ketmar ©   (2006-08-01 18:50) [17]

>Andr-04   (01.08.06 15:55) [15]
ничего ты не понял. "понял" -- это не "и всё", а "потому что".

>Сергей М. ©   (01.08.06 16:53) [16]
тут, похоже, просто ждут, пока весь нужный текст из справки на русский переведут. вот ты в [13] начал, после чего в [15] честно признались. %-)


 
Ketmar ©   (2006-08-01 18:54) [18]

кстати, только что обратил внимание на дезинформацию в [5]: "я с сокетами всегда только в блокирующем режиме работал". после чего желание как-то помогать пропало вовсе -- не люблю лжецов.


 
Andr-04   (2006-08-02 12:38) [19]

Да, в блокирующем и работал. Но не было необходимости принимать сообщения от сервера!
А я тем временем упорно разбирал документацию и переводил часть кода на асинхронный режим. Короче, в приведённом мной коде в [5] WSAGetLastError выдаёт WSAEFAULT (10014).
Прошу извинить за всё написанное мной выше - постараюсь больше этого не делать: буду писать сюда только после достаточного чтения доки и не экономить время на этом! Ато отвечают тут быстро :-) Спасибо!


 
Сергей М. ©   (2006-08-02 12:50) [20]

WSAEFAULT (10014) The buf argument is not totally contained in a valid part of the user address space.


 
Andr-04   (2006-08-02 13:17) [21]

Да знаю я описание этой ошибки. Только не понимаю почему она возникает! Переменная ига описана как динамический массив (array of byte), размер которого устанавливется предварительно при помощи SetLength, где в качестве размера выступает fBufSize.


 
Сергей М. ©   (2006-08-02 13:28) [22]


> не понимаю почему она возникает


А нефиг манипулировать GetSockOpt(), если не понимаешь, что там происходит и почему.


 
Ketmar ©   (2006-08-02 13:31) [23]

> [21] Andr-04   (02.08.06 13:17)

тогда с чего делается send() с просто buf? и советую проверить, не используется ли buf ещё где-то таким же образом. просто buf даст указатель совсем не туда, куда buf[0].


 
Andr-04   (2006-08-02 13:43) [24]

И с buf, и с buf[0], и с простой переменной типа Cardinal. Ещё пробовал использовать ioctlsocket(fSocket,FIONREAD,sz), после выполнения которой sz возвращает 0. Но Send работает без проблем! И ещё: если Send вызывать с buf[0], то она тоже вернёт (-1)!


 
Сергей М. ©   (2006-08-02 13:46) [25]

Тебе вообще накой ляд Winsock потребовался ?
Чем готовые компоненты не устроили ?


 
Сергей М. ©   (2006-08-02 13:48) [26]


> если Send вызывать с buf[0], то она тоже вернёт (-1)


Угу .. И еще неделю выяснять будем, что говорит при этом WSAGetLastError()

И накой тут сдался дин.массив - одному тебе известно.


 
Andr-04   (2006-08-02 14:09) [27]

Значение какой массив - динамический или статический не имеет.
> И еще неделю выяснять будем, что говорит при этом WSAGetLastError()
Не утрируйте! WSAGetLastError выдаёт 0, т.е. всё OK. А использовать готовые компоненты смысла нет - модуль пишу. Для чего - не скажу, потому что унижать будете! Вобщем, это не имеетзначения!


 
Andr-04   (2006-08-02 14:21) [28]

Ну я и мудило! Столько и времени, и места на форуме угробыл! Мда... Короче, тему можно закрыть, а лучше и удалить, потому что от неё больше никакого толка никому не будет! Я в сервере указывал на передачу пустого буфера из Stream, из-за того, что забыл назначить нулевую позицию именно в Stream"е! И читаю конец, спокойный такой! Не внимательно получилось!


 
Сергей М. ©   (2006-08-02 14:28) [29]


> Andr-04   (02.08.06 14:09) [27]


> Значение какой массив - динамический или статический не
> имеет


Может и не имеет. А вот выбор размера массива имеет.


> WSAGetLastError выдаёт 0


Этого не может быть. потому что этого не может быть никогда (с)

Справка к send() гласит:

Return Values

If no error occurs, send returns the total number of bytes sent. (Note that this can be less than the number indicated by len.) Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.

Ты когда-нибудь научишься ее читать, ту самую справку ?


> использовать готовые компоненты смысла нет - модуль пишу


С каких пор использование готовых компонентов потеряло смысл ?
И при чем здесь модуль ?


> Для чего - не скажу


Сексот ты наш)


> это не имеетзначения


Имеет ! Еще как имеет !

Трассируя пошагово чужой (заведомо работоспособный) модуль ты приобретаешь необходимые знания.


 
Сергей М. ©   (2006-08-02 14:30) [30]


> в сервере указывал на передачу пустого буфера из Stream,
>  из-за того, что забыл назначить нулевую позицию именно
> в Stream"е! И читаю конец, спокойный такой


Ты гонишь.

recv() в этом случае никак не может вернуть SOCKET_ERROR.


 
Andr-04   (2006-08-02 14:44) [31]

У меня теперь другая проблема - после вызова send программа аварийно завершается, хотя сервер это сообщение благополучно получает!..


 
Сергей М. ©   (2006-08-02 14:52) [32]

Проотладчик ты, разумеется, слыхом не слыхивал.
Значит тебе пора закругляться с потугами на поприще программинга.


 
Andr-04   (2006-08-02 14:59) [33]

А, всё, разобрался! Форум уже в чат превратился по моей милости! Опять неправильно с динамическим массивом работал. ВЕЗДЕ нужно указывать buf[0]! Да будет это мне уроком! Очень извиняюсь за отнятое время! Спасибо всем!


 
Сергей М. ©   (2006-08-02 15:00) [34]

Малацца.
Еще бы ты разобрался с Get/SetSockOpt - цены б тебе не было.


 
Andr-04   (2006-08-02 15:01) [35]


> Проотладчик ты, разумеется, слыхом не слыхивал.
> Значит тебе пора закругляться с потугами на поприще программинга.

Какраз-таки отладчик мне это и сказал! А программировать заканчивать я и не думаю! Ещё только 6 лет программирую - мало ещё! :-)


 
Andr-04   (2006-08-02 15:07) [36]


> Еще бы ты разобрался с Get/SetSockOpt - цены б тебе не было.

Да, уже и с этим успел познакомиться, но лишь всколзь. Если будут опять проблемы - впервую очередь это почитаю! Мне очень помогла статья из королевства
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1021&mode=print Ну и её вторая часть...


 
Сергей М. ©   (2006-08-02 15:08) [37]

Ну тады, возвращаясь к нашим баранам, какое отношение все это имеет к  WSAAsyncSelect ?


 
medved_68 ©   (2006-08-02 15:12) [38]


> Ещё только 6 лет программирую - мало ещё! :-)


> нужно указывать buf[0]!

Шесть лет!!!! Ну вот сейчас ты точно гонишь.


 
Ketmar ©   (2006-08-02 15:36) [39]

> [33] Andr-04   (02.08.06 14:59)

я тебе на это уже давно намекал. %-)


 
Сергей М. ©   (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 свой написал?


 
Andr-04   (2006-08-04 13:45) [81]

И недоработки в KOL.pas исправлял?.. Это я к примеру, но не ограничиваясь.


 
Сергей М. ©   (2006-08-04 13:55) [82]


> Когда могу разобраться в этих исходниках - так и делаю


Значит следовало честно сказать - я, мол, не могу разобраться в исходниках scktcomp.pas)


> На основе чего, Вы думаете, я SockStream свой написал?


Понятия не имею, что есть этот самый SockStream.
Зато вижу, что на предмет грамотной обработки FD_WRITE/CLOSE-событий ты не приложил усилий по анализу тех же исходников)


 
Andr-04   (2006-08-04 19:44) [83]

> Значит следовало честно сказать - я, мол, не могу разобраться
> в исходниках scktcomp.pas)

Я в них не разбирался - мне вполне хватило kolTCPSocket.pas (см. пост 56).

> Понятия не имею, что есть этот самый SockStream.
А его и нету! Я его сделал для собственных нужд.

> Зато вижу, что на предмет грамотной обработки FD_WRITE/CLOSE-
> событий ты не приложил усилий по анализу тех же исходников)

Зато благодаря таким людям как Вы, теперь всё исправил! На счёт close - невнимательность, а write - сервер выполняет не функции прокси, поэтому переполнения там не будет! Но я всё равно перестраховался и поправил. :-)


 
Сергей М. ©   (2006-08-05 19:15) [84]


> мне вполне хватило kolTCPSocket.pas


Оно и заметно, судя твоим по вопросам


> его и нету! Я его сделал для собственных нужд


Стоить ли выпячивать поделки, не имеющие отношения к логике транспорта ?


> write - сервер выполняет не функции прокси


Да по барабану, прокси или не прокси)
Транспорт лежит уровнем ниже !
Читай про модель OSI до полного просветления.


 
Andr-04   (2006-08-05 22:55) [85]

> Оно и заметно, судя твоим по вопросам
Мои вопросы не затрагивают исходники готовых модулей. Сервер мой, код которого я приводил, работал, пусть немного был и некорректным из-за невнимательности и из-за того, что некоторым вещам я не придавал существенного значения. Да и тему эту бы не создавал, если бы в стрейме, опять по невнимательности, не забыл бы указать начальную позицию. Мда... Невнимательность меня подводит - код большой из-за того, что мало общих процедур, поэтому как что-нибудь изменю в одном месте, приходится вводить коррективы и в остальных частях. Всё, в следующих своих проектах будут сплошные процедуры! :-D

> Стоить ли выпячивать поделки, не имеющие отношения к логике
> транспорта ?

Это я пример привёл к тому, что исходники я тоже ковыряю.

> Да по барабану, прокси или не прокси)
> Транспорт лежит уровнем ниже !
> Читай про модель OSI до полного просветления.

Я же сказал, что перестраховался и исправил! Более того, всегда буду делать подобным образом!


 
Медведъ   (2006-08-07 10:11) [86]

>Andr-04   (05.08.06 22:55) [85]
процедуры это ты хорошо придумал, еще не забывай про функции


 
Andr-04   (2006-08-07 12:42) [87]

> процедуры это ты хорошо придумал, еще не забывай про функции
:-D Ну уж это само собой!



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

Текущий архив: 2006.12.24;
Скачать: CL | DM;

Наверх




Память: 0.74 MB
Время: 0.069 c
9-1139717450
Уважаемый Автор
2006-02-12 07:10
2006.12.24
На каких англоязычных сайтах можно зарегить свою игрушку?


2-1165392523
Roman_ln
2006-12-06 11:08
2006.12.24
список ComboBox функция поиска элемента


3-1160631391
nstur
2006-10-12 09:36
2006.12.24
Как программно создать MDB файл


15-1164158780
Дядя
2006-11-22 04:26
2006.12.24
Что такое кубит? И квантовый компьютер вообще?


3-1160896783
Winni
2006-10-15 11:19
2006.12.24
Password для БД в BDE