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

Вниз

Вопрос по WSA (WinSocket API).   Найти похожие ветки 

 
Новичек ©   (2005-06-21 14:09) [0]

Уважаемые знатоки, понадобилось мне написать в Delphi программку для работы с сокетами на низком уровне. Написать-то написал, да вот сомнения меня терзают - всё ли там в порядке?
Вот код:

procedure MyProcedure;
var
 vSocket: TSocket;
 vSockAddr: TSockAddr;
 aBuf: array [0..2048] of char;
 pEvent: WSAEVENT;
 ConnectError: Integer;
 NetworkEvents: TWSANetworkEvents;
 
 procedure SendStr(Str: string);
 var
  C: char;
 begin
   while (length(Str) > 0) do
     begin
       C := Str[1];
       delete(Str, 1, 1);
       Send(vSocket, C, 1, 0);
     end;
 end;
begin
 pEvent := WSA_INVALID_EVENT;
 pEvent := WSACreateEvent();
 FillChar(vSockAddr, SizeOf(TSockAddr), 0);
 vSockAddr.sin_family := AF_INET;
 vSockAddr.sin_port := htons(5000);
 vSockAddr.sin_addr.S_addr := inet_addr("127.0.0.1");
 vSocket := WinSock2.Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 if vSocket = INVALID_SOCKET then Halt(1);
 WSAEventSelect(vSocket, pEvent, FD_READ);
 WinSock2.Connect(vSocket, @vSockAddr, SizeOf(vSockAddr));
//Дожидаюсь разрешения на чтение:
 WSAWaitForMultipleEvents(1, @pEvent, FALSE, WSA_INFINITE, FALSE);
 WSAResetEvent(pEvent);
//Принимаю стартовый пакет сервера и обнуляю буфер приема:
 Recv(vSocket, aBuf, SizeOf(aBuf), 0);
 aBuf := "";
//Дожидаюсь разрешения на чтение:
 WSAWaitForMultipleEvents(1, @pEvent, FALSE, WSA_INFINITE, FALSE);
//Принимаю приветствие сервера, заканчивающееся символом "<"и обнуляю буфер приема:
//символом "<":
 repeat
   Recv(vSocket, aBuf, SizeOf(aBuf), 0);
 until Pos("<", aBuf) <> 0;
 aBuf := "";
 WSAResetEvent(pEvent);
 SendStr("Hello, Dolly" + #13#10);
 WSAWaitForMultipleEvents(1, @pEvent, FALSE, WSA_INFINITE, FALSE);
//Здесь я должен дождаться ответа сервера:
 repeat
   Recv(vSocket, aBuf, SizeOf(aBuf), 0);
 until Pos("Well, hello", aBuf) <> 0;
 aBuf := "";
 WSAResetEvent(pEvent);
 SendStr("Good by" + #13#10);
 WSAResetEvent(pEvent);
 CloseSocket(vSocket);
 WSACleanup;
end;

Меня интересует, а правильно ли я распоряжаюсь Event"ами? И как запрограммировать больше событий - для каждого делать CreateEvent?
Спасибо.


 
Digitman ©   (2005-06-21 14:21) [1]


> правильно ли я распоряжаюсь Event"ами


думаю, неправильно.

все преимущества асинхронной работы с гнездом с использованием событийного механизма нотификаций  этим кодом ты свел на нет, реализовав в конечном итоге обычный синхронный алгоритм

кр. того, создавая ивент-объект ты становишься ответственным за его уничтожение, коего в твоем коде нет


 
Новичек ©   (2005-06-21 14:24) [2]

Эх, я и подозревал нечто подобное :-( Буду переделывать.
Спасибо.


 
Digitman ©   (2005-06-21 15:05) [3]


> как запрограммировать больше событий - для каждого делать
> CreateEvent?


зачем ?

в справке же черным по белому написано :

to associate an event object with both reading and writing network events, the application must call WSAEventSelect with both FD_READ and FD_WRITE, as follows:

rc = WSAEventSelect(s, hEventObject, FD_READ|FD_WRITE);
 

It is not possible to specify different event objects for different network events. The following code will not work; the second call will cancel the effects of the first, and only FD_WRITE network event will be associated with hEventObject2:

rc = WSAEventSelect(s, hEventObject1, FD_READ);
rc = WSAEventSelect(s, hEventObject2, FD_WRITE); //bad
 

To cancel the association and selection of network events on a socket, lNetworkEvents should be set to zero, in which case the hEventObject parameter will be ignored.


 
Polevi ©   (2005-06-21 15:49) [4]

да не будет это работать, где анализ результатов вызова ф-ий


 
Новичек ©   (2005-06-21 16:12) [5]

Наверное, следует сделать как-то так:


WSAEventSelect(vSocket, pEvent, FD_READ or FD_WRITE or FD_CONNECT);
...
 WSAEnumNetworkEvents(vSocket, pEvent, @NetworkEvents);

 case NetworkEvents.lNetworkEvents of
   FD_CONNECT: PostMessage(MainWnd, WM_MESSAGE, 0, 2);
   FD_READ: PostMessage(MainWnd, WM_MESSAGE, 0, 3);
   FD_WRITE: PostMessage(MainWnd, WM_MESSAGE, 0, 4);
   else PostMessage(MainWnd, WM_MESSAGE, 0, 5);
 end;


PostMessage взят, разумеется, только для примера.
Правильно я понял?


 
Digitman ©   (2005-06-21 17:11) [6]


> Новичек ©   (21.06.05 16:12) [5]


да, WSAEnumNetworkEvents() - не худший способ "разбора", даже порой лучше и удобнее (удобнее хотя бы потому что явный WSAResetEvent не требуется)


 
Новичек ©   (2005-06-21 17:13) [7]

Так-с, дело сдвинулось :-) Появилось направление копания :-)
Спасибо большое!
(Будете в Новороссийске - пиво с меня :-) )


 
Digitman ©   (2005-06-21 17:47) [8]


> Новичек ©   (21.06.05 17:13) [7]


а як же ж ?)

разумеется - с тебя)


 
Digitman ©   (2005-06-21 17:59) [9]

только не забывай , что в ряде случаев при "разборе" с пом. WSAEnumNetworkEvents() можно и должно анализировать возвращаемый ей не только массив кодов событий, но и сопутствующий массив кодов ошибок соотв.событий

иначе рано или поздно вляпаешься по самое нехочу


 
Новичек ©   (2005-06-21 18:08) [10]

Ага, понял. Учту, спасибо.



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

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

Наверх




Память: 0.49 MB
Время: 0.038 c
8-1114110608
clampo
2005-04-21 23:10
2005.10.09
Плейлист


1-1127205297
Nait
2005-09-20 12:34
2005.10.09
как перехватить событие для Application (например х,y мышки)?


1-1127047828
MBoris
2005-09-18 16:50
2005.10.09
Word Application


14-1126707015
Prohodil Mimo
2005-09-14 18:10
2005.10.09
Радуйтесь! я на клаву наклейки повесил :о)


2-1125459771
AlexanderS
2005-08-31 07:42
2005.10.09
Ошибка с OpenDialog