Форум: "Сети";
Текущий архив: 2002.02.25;
Скачать: [xml.tar.bz2];
ВнизПередача срочных данных Найти похожие ветки
← →
soloboev (2001-11-21 14:36) [0]Спецы, выручайте, надежда только на вас. Нужно передать на
машину с Windows срочные данные - send(s,"a",1,MSG_OOB). Убился уже, ничего не получается. Данные удается прочитать, только если сокет работает в неблокировочном режиме. Для меня этот режим поряду причин не приемлем. Если сокет работает в блокировочном режиме, возникает следующая ситуация. Командой ioctlsocket(s,SOICATMARK,r) определяю, что есть срочные данные. Это работает. После этого пытаюсь recv(s,oob_buf,1,MSG_OOB) - ждет до бесконечности. Посоветуйте пожалуйста что-нибудь, может хотя бы ссылку.
← →
Digitman (2001-11-22 08:40) [1]объясни, чем в данном случае вызвана необходимость передавать строки в OOB-пакетах ?
← →
soloboev (2001-11-23 09:16) [2]Ну, надо мне
← →
Digitman (2001-11-23 12:19) [3]а принимающее гнездо имеет установленную опцию SO_OOBINLINE ? и вообще - оно SOCK_STREAM у тебя ?
← →
soloboev (2001-11-26 15:24) [4]Вот это уже лучше. В общем, ситуация такая. Сокет естественно STREAM"ный.
Если включаешь опцию SO_OOBINLINE, определить наличие OOB данных можно ioctlsocket(s,SIOCATMARK,r); Но приэтом естественно recv(s,buf,1,0) ждет до бесконечности, а resv(s,buf,1,MSG_OOB) чудесно выполняется, но при этом
содержимое buf не меняется, а данные вылазят вообще черт-те когда. Дело
в том, что это все делается под Windows 98 и реально работает только
один способ - использовать функцию WSAAsyncSelect. Правда это неблокирующий сокет, но эту проблему я решил. Думал, что советов будет больше.
← →
Digitman (2001-11-26 16:22) [5]>soloboev
"работает только один способ - использовать функцию WSAAsyncSelect".
Да ничего подобного ! Там, где работает WSAAsyncSelect, с тем же успехом будет работать и WSAEventSelect - оба режима переводят гнездо в неблокирующий режим
← →
soloboev (2001-11-28 11:24) [6]Все правильно - но я описал рабочий вариант. Для функций, работающих с
WSAEventSelect у меня нет библиотек (описания функций, константы). Если
знаешь, где взять, подскажи.
← →
Digitman (2001-11-28 12:03) [7]>soloboev
А какие тебе еще библиотеки-то нужны ? И WSAAsyncSelect и WSAEventSelect экспортируются одной и той же библиотекой WS2_32.DLL, описание их есть в хэлпе, работают очень похоже (в WSAEventSelect гнездо ассоциируется с объектом синхронизации, создаваемым по WSACreateEvent, а в WSAAsyncSelect гнездо ассоциируется с любым существующим hWnd).
Декларацию же WSAEventSelect и пример использования ты можешь найти в модуле SConnect.pas
← →
soloboev (2001-11-28 16:40) [8]Там нет декларации например WSAWaitForMultipleEvents или WSA_MAXIMUM_WAIT_EVENTS, да и многих других нужных для этого метода
деклараций я не нашел. Не нашел в D5 и в D6. Видимо по ряду причин
тот способ, которым я воспользовался, самый приемлемый. Но это под
Windows 98. Под Linux например все описанные в документации способы
работают без проблем.
← →
Digitman (2001-11-28 16:53) [9]1. Декларация всех потрохов Winsock2 есть в свободно распространяемом winsock2.pas. В сети море узлов, где можно скачать этот модуль.
2. Даже если у тебя нет какой-то декларации, у тебя под рукой есть хэлп, сотвори ее сам по образу и подобию их декларации в sconnect.pas.
3. На кой черт тебе этот WSAWaitForMultipleEvents ? Пользуйся обычным MsgWaitForMultipleObjects - он еще и сообщения, посланные потоку другими потоками, будет отслеживать (WSAWaitForMultipleEvents этого не делает!)
← →
soloboev (2001-12-03 15:38) [10]Может подкинешь кусочек кода, в качестве иллюстрации
← →
Digitman (2001-12-03 15:50) [11]Иллюстрации чего ? декларации или использования ? конкретно - чего ?
← →
soloboev (2001-12-04 11:42) [12]Можно того и другого :-) по WSAEventSelect.
← →
Digitman (2001-12-04 13:55) [13]модуль sconnect.pas (мог бы и сам сподобиться заглянуть туда)
interface
....
function LoadWinSock2: Boolean;
var
WSACreateEvent: function: THandle stdcall;
WSAResetEvent: function(hEvent: THandle): Boolean stdcall;
WSACloseEvent: function(hEvent: THandle): Boolean stdcall;
WSAEventSelect: function(s: TSocket; hEventObject: THandle; lNetworkEvents: Integer): Integer stdcall;
...
implementation
...
var
hWinSock2: THandle;
...
function LoadWinSock2: Boolean;
const
DLLName = "ws2_32.dll";
begin
Result := hWinSock2 > HINSTANCE_ERROR;
if Result then Exit;
hWinSock2 := LoadLibrary(PChar(DLLName));
Result := hWinSock2 > HINSTANCE_ERROR;
if Result then
begin
WSACreateEvent := GetProcAddress(hWinSock2, "WSACreateEvent");
WSAResetEvent := GetProcAddress(hWinSock2, "WSAResetEvent");
WSACloseEvent := GetProcAddress(hWinSock2, "WSACloseEvent");
WSAEventSelect := GetProcAddress(hWinSock2, "WSAEventSelect");
end;
end;
procedure FreeWinSock2;
begin
if hWinSock2 > HINSTANCE_ERROR then
begin
WSACreateEvent := nil;
WSAResetEvent := nil;
WSACloseEvent := nil;
WSAEventSelect := nil;
FreeLibrary(hWinSock2);
end;
hWinSock2 := 0;
end;
...
function TSocketTransport.GetWaitEvent: THandle;
begin
FEvent := WSACreateEvent;
WSAEventSelect(FSocket.SocketHandle, FEvent, FD_READ or FD_CLOSE);
Result := FEvent;
end;
...
procedure TTransportThread.Execute;
procedure SynchronizeException;
var
SendException: TObject;
begin
if RaiseList <> nil then
begin
SendException := PRaiseFrame(RaiseList)^.ExceptObject;
PRaiseFrame(RaiseList)^.ExceptObject := nil;
if Assigned(FTransport) and (SendException is ESocketConnectionError) then
FTransport.Connected := False;
PostMessage(FParentHandle, THREAD_EXCEPTION, 0, Integer(Pointer(SendException)));
end;
end;
var
msg: TMsg;
Data: IDataBlock;
Event: THandle;
Context: Integer;
begin
CoInitialize(nil);
try
PeekMessage(msg, 0, WM_USER, WM_USER, PM_NOREMOVE);
ReleaseSemaphore(FSemaphore, 1, nil);
try
FTransport.Connected := True;
try
Event := FTransport.GetWaitEvent;
while not Terminated and FTransport.Connected do
try
case MsgWaitForMultipleObjects(1, Event, False, INFINITE, QS_ALLINPUT) of
WAIT_OBJECT_0:
begin
WSAResetEvent(Event);
Data := FTransport.Receive(False, 0);
if Assigned(Data) then
begin
Data._AddRef;
PostMessage(FParentHandle, THREAD_RECEIVEDSTREAM, 0, Integer(Pointer(Data)));
Data := nil;
end;
end;
WAIT_OBJECT_0 + 1:
begin
while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do
begin
if (msg.hwnd = 0) then
case msg.message of
THREAD_SENDSTREAM:
begin
Data := IDataBlock(msg.lParam);
Data._Release;
Context := FTransport.Send(Data);
if msg.wParam = 1 then
begin
Data := FTransport.Receive(True, Context);
Data._AddRef;
PostMessage(FParentHandle, THREAD_RECEIVEDSTREAM, 0, Integer(Pointer(Data)));
Data := nil;
end else
PostMessage(FParentHandle, THREAD_SENDNOTIFY, 0, 0);
end;
THREAD_REPLACETRANSPORT:
begin
FTransport := ITransport(msg.lParam);
FTransport._Release;
end;
else
DispatchMessage(msg);
end
else
DispatchMessage(msg);
end;
end;
end;
except
SynchronizeException;
end;
finally
Data := nil;
FTransport.Connected := False;
end;
except
SynchronizeException;
end;
finally
FTransport := nil;
CoUninitialize();
end;
end;
← →
soloboev (2001-12-05 09:22) [14]Спасобо, открыл глаза.
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2002.02.25;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.005 c