![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос по WSA (WinSocket API). [D7, WinXP]
Новичек © (2005-06-21 14:09:00)Уважаемые знатоки, понадобилось мне написать в 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?
Спасибо.
Новичек (2005-06-21 18:08:00) [1]Ага, понял. Учту, спасибо.
Digitman (2005-06-21 17:59:00) [2]только не забывай , что в ряде случаев при "разборе" с пом. WSAEnumNetworkEvents() можно и должноанализировать возвращаемый ей не только массив кодов событий, но и сопутствующий массив кодов ошибок соотв.событий
иначе рано или поздно вляпаешься по самое нехочу
Digitman (2005-06-21 17:47:00) [3]
> Новичек © (21.06.05 17:13) [7]
а як же ж ?)
разумеется - с тебя)
Новичек (2005-06-21 17:13:00) [4]Так-с, дело сдвинулось :-) Появилось направление копания :-)
Спасибо большое!
(Будете в Новороссийске - пиво с меня :-) )
Digitman (2005-06-21 17:11:00) [5]
> Новичек © (21.06.05 16:12) [5]
да, WSAEnumNetworkEvents() - не худший способ "разбора", даже порой лучше и удобнее (удобнее хотя бы потому что явный WSAResetEvent не требуется)
Новичек (2005-06-21 16:12:00) [6]Наверное, следует сделать как-то так:
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 взят, разумеется, только для примера.
Правильно я понял?
Polevi (2005-06-21 15:49:00) [7]да не будет это работать, где анализ результатов вызова ф-ий
Digitman (2005-06-21 15:05:00) [8]
> как запрограммировать больше событий - для каждого делать
> 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.
Новичек (2005-06-21 14:24:00) [9]Эх, я и подозревал нечто подобное :-( Буду переделывать.
Спасибо.
Digitman (2005-06-21 14:21:00) [10]
> правильно ли я распоряжаюсь Event'ами
думаю, неправильно.
все преимущества асинхронной работы с гнездом с использованием событийного механизма нотификаций этим кодом ты свел на нет, реализовав в конечном итоге обычный синхронный алгоритм
кр. того, создавая ивент-объект ты становишься ответственным за его уничтожение, коего в твоем коде нет