Текущий архив: 2011.10.02;
Скачать: CL | DM;
Вниз
Проблема с SendText в ctBlocking сокете Найти похожие ветки
← →
FireMan_Alexey © (2009-05-21 16:55) [40]Я понял, поэтому и предложил использовать с определенной задержкой, а не бесконечной! :)
У Автора будет еще много вопросов :), хотя в [4] я предлагал использовать Select. Со своего опыта знаю, что с этой функцией гемора меньше :)
← →
FireMan_Alexey © (2009-05-21 17:20) [41]
> Alex_C
Чтобы первое пришло FD_CONNECT поменяй местами If-ы :)
← →
Alex_C (2009-05-21 21:36) [42]
> FireMan_Alexey © (21.05.09 16:24) [36]
> Хочешь кину тебе исходник моего класса сокета специально
> для потока?
> Он сделан по другому...
Очень хочу!
Вообще хочу достаточно досканально разобраться с работой сокетов, т.к. в дальнейшем предстоит решить при их помощи достаточно серьезную задачу.
← →
Alex_C (2009-05-21 21:56) [43]
> Чтобы первое пришло FD_CONNECT поменяй местами If-ы :)
Ну это тут не причем )))
Последовательность прихода сообщений от последовательности if-ов не зависит. Хотя тут вот тоже пока непонятность - почему меняется последовательность?
← →
Сергей М. © (2009-05-22 08:39) [44]
> почему меняется последовательность?
>
Ничего она не меняется, не выдумывай.
FD_CONNECT всегда возбуждается первым, вне зависимости будут ли при этом одновременно возбуждаться FD_WRITE и FD_READ.
Поставь строкуif GetEvent(Ev.lNetworkEvents,FD_CONNECT) then
на самый верх цепочки строк-проверок, как тебе сказал FireMan_Alexey ©, и убедись в этом)
FD_WRITE же обычно возбуждается одновременно с FD_CONNECT.
Одновременно взведенные флаги FD_CONNECT | FD_WRITE показывают, что соединение установлено и готово к передаче.
При проверке событийных флагов следует обязателоьно проверять соответствующие событиям коды ошибок. Так, например, попытка коннекта, приведшая к событию FD_CONNECT, еще не говорит об успешном коннекте. Об успешности коннекта можно судить только проанализировав Ev.iErrorCode[FD_CONNECT_BIT]. Тоже самое касается и всех прочих событий без исключения.
← →
Alex_C (2009-05-22 11:26) [45]
> Ничего она не меняется, не выдумывай.
Честно признаюсь - выдумал )))
Сейчас все внимательно проверил и нашел у себя ошибку! Естественно событие коннект приходит первым и никак иначе.
> Об успешности коннекта можно судить только проанализировав
> Ev.iErrorCode[FD_CONNECT_BIT]. Тоже самое касается и всех
> прочих событий без исключения.
Я так и делаю:
if GetEvent(Ev.lNetworkEvents,FD_CONNECT) then
begin
if Ev.iErrorCode[FD_CONNECT_BIT]<>0 Then
begin
if Assigned(FOnErrorEvent) then
Synchronize(OnErrorEventProcedure);
Break;
end
else
begin
FSocketState := wsConnected;
if Assigned(FOnConnectEvent) then
Synchronize(OnConnectProcedure);
end;
end;
← →
FireMan_Alexey © (2009-05-22 13:41) [46]За код не ругать делал для себя:
unit NewSock;
interface
Uses WinSock;
CONST
SOCKET_ERROR=WINSOCK.SOCKET_ERROR;
Type
TNewSock=Class
Private
FSock :Integer;
FClose :Boolean;
FError :Integer;
FCanRead :Boolean;
FCanWrite:Boolean;
FOnError :Boolean;
FAddr :TSockAddr;
FHost :String;
FPort :Word;
Public
Procedure Close;
Procedure GetStatus(Const TimeOut:Integer=50);
Function GetRemoteAddress:Integer;
Function GetRemoteHost:String;
Function Connect:Boolean;
Function Write(Var Buff; Size:Integer):Integer;
Function Read (Var Buff; Size:Integer):Integer;
Function ReceiveLength:Integer;
Constructor Create(Const Sock:Integer=Invalid_Socket);
Destructor Destroy;Override;
Property Host:String Read FHost Write FHost;
Property Port:Word Read FPort Write FPort;
Property CanRead:Boolean Read FCanRead;
Property CanWrite:Boolean Read FCanWrite;
Property Disconnected:Boolean Read FClose;
Property ErrorPresent:Boolean Read FOnError;
Property Error:Integer Read FError;
Property SocketHandle:TSocket Read FSock;
End;
Function InetAddr(Addr:Integer):String;
implementation
Constructor TNewSock.Create;
Begin
Inherited Create;
FClose:=Sock=Invalid_Socket;
FSock:=Sock;
{IF Not FClose Then
Begin
FCanWrite:=True;
End
Else}
FCanWrite:=False;
FCanRead:=False;
FOnError:=False;
FError:=0;
End;
Destructor TNewSock.Destroy;
Begin
//
Close;
Inherited Destroy;
End;
Procedure TNewSock.Close;
Begin
If FSock<>Invalid_Socket Then
Begin
If CloseSocket(FSock)<>0 Then
Begin
FError:=WSAGetLastError;
FOnError:=True;
End;
FSock:=Invalid_Socket;
FCanRead:=False;
FCanWrite:=False;
End;
FClose:=True;
End;
Procedure TNewSock.GetStatus;
Var
FD_READS,FD_WRITES,FD_ERROR:TFDSET;
T:TTimeVal;
R:Integer;
Begin
//
If FClose Then Exit;
T.tv_usec:=TimeOut Mod 1000;
T.tv_sec:=TimeOut Div 1000;
FD_ZERO(FD_READS);
FD_SET(FSock,FD_READS);
FD_WRITES:=FD_READS;
FD_ERROR:=FD_READS;
//FD_SET(FSock,FD_WRITES);
R:=Select(1,@FD_READS,@FD_WRITES,@FD_ERROR,@T);
If R=Socket_Error Then
Begin
FError:=WSAGetLastError;
FOnError:=True;
Exit;
End
Else FError:=0;
If R>0 Then
Begin
If FD_ISSET(FSock,FD_READS) Then FCanRead:=True
Else FCanRead:=False;
If FD_ISSET(FSock,FD_WRITES) Then FCanWrite:=True;
If FD_ISSET(FSock,FD_ERROR) Then
Begin
FOnError:=True;
R:=SizeOf(FError);
R:=GetSockOpt(FSock,SOL_SOCKET,SO_ERROR,@FError,R);
{If R=SOCKET_ERROR Then
FError:=WSAGetLastError;}
End
Else
FOnError:=False;
End;
End;
Function TNewSock.GetRemoteAddress;
Var
_Addr:TSockAddr;
_Size:Integer;
Begin
Result:=-1;
If Not FClose Then
Begin
_Size:=SizeOf(_Addr);
FError:=GetPeerName(FSock,_Addr,_Size);
If FError=SOCKET_ERROR Then
Begin
FError:=WSAGetLastError;
FOnError:=True;
Exit;
End;
Result:=_Addr.sin_addr.S_addr;
End;
End;
Function TNewSock.GetRemoteHost;
Var
_Addr:Integer;
Host:PHostEnt;
Begin
_Addr:=GetRemoteAddress;
Host:=GetHostByAddr(@_Addr,SizeOf(_Addr),AF_INET);
Result:="";
If Host<>Nil Then Result:=Host.h_name;
End;
Function TNewSock.Write;
Var
R:Integer;
Begin
R:=Send(FSock,Buff,Size,0);
If R=SOCKET_ERROR Then
Begin
FError:=WSAGetLastError;
If FError=WSAEWOULDBLOCK Then
Begin
FCanWrite:=False;
R:=0;
FError:=0;
End
Else FOnError:=True;
End;
Result:=R;
End;
Function TNewSock.Read;
Var
R:Integer;
Begin
R:=Recv(FSock,Buff,Size,0);
If R=0 Then
Close;
If R=SOCKET_ERROR Then
Begin
FError:=WSAGetLastError;
If FError=WSAEWOULDBLOCK Then
Begin
FCanRead:=False;
FError:=0;
End
Else FOnError:=True;
R:=0;
End;
Result:=R;
End;
Function TNewSock.ReceiveLength;
Begin
If IOCTLSocket(FSock,FIONREAD,Result)=SOCKET_ERROR Then
Begin
FError:=WSAGetLastError;
FOnError:=True;
End;
End;
Function TNewSock.Connect;
Var
PHost:PHostEnt;
R:Integer;
Begin
Result:=False;
If Not FClose Then Exit;
If FHost="" Then Exit;
If FPort=0 Then Exit;
FSock:=Socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
If FSock=Invalid_Socket Then
Begin
FError:=WSAGetLastError;
FOnError:=True;
Close;
Exit;
End;
FAddr.sin_family:=AF_INET;
FAddr.sin_port:=HToNS(FPort);
FAddr.sin_addr.S_addr:=Inet_addr(PChar(FHost));
If FAddr.sin_addr.S_addr=INADDR_NONE Then
Begin
PHost:=GetHostByName(PChar(FHost));
If PHost=Nil Then
Begin
FError:=WSAGetLastError;
FOnError:=True;
Exit;
End;
Move(PHost^.h_addr_list^[0],
FAddr.sin_addr,
PHost^.h_length);
End;
R:=WinSock.Connect(FSock,FAddr,SizeOF(FAddr));
If R=SOCKET_ERROR Then
Begin
FError:=WSAGetLastError;
FOnError:=True;
Exit;
End;
FClose:=False;
Result:=True;
End;
Function InetAddr;
Var
_Addr:TSockAddr;
Begin
_Addr.sin_addr.S_addr:=Addr;
Result:=inet_ntoa(_Addr.sin_addr);
End;
VAR
WSAD:TWSAData;
Initialization
Begin
WSAStartup($202,WSAD);
End;
Finalization
Begin
WSACleanup;
End;
end.
← →
FireMan_Alexey © (2009-05-22 13:46) [47]Используем так:
...
TvoySocket:=TNewSock.Create;
TvoySocket.Host:="127.0.0.1";
TvoySocket.Port:=???;
If Not TvoySocket.Connect Then
Begin
Error:=TvoySocket.Error;
TvoySocket.Close;
End;
While not Terminated Do
Begin
TvoySocket.GetStatus;
If TvoySocket.CanRead Then //Chitaem ;
If tvoySocket.CanWrite Then //Pishem;
If TvoySocket.ErrorPresent Then //Error!;
End;
TvoySocket.Free;
...
← →
FireMan_Alexey © (2009-05-22 13:54) [48]If Not TvoySocket.Connect Then
Begin
Error:=TvoySocket.Error;
TvoySocket.Close;
Exit;//Забыл :)
End;
← →
FireMan_Alexey © (2009-05-22 14:00) [49]Да и:
If TvoySocket.ErrorPresent Then //Error ! ;
Можно первым поставить :)
← →
FireMan_Alexey © (2009-05-22 14:45) [50]Да еще забыл, там нужна строчка:
If TvoySocket.Disconnected Then Break;
← →
Alex_C (2009-05-22 21:13) [51]
> FireMan_Alexey
Спасибо! Очень интересная реализация! Буду изучать!
После чего задам вопросы )))
← →
FireMan_Alexey © (2009-05-23 12:28) [52]Не забывай, что при CanRead необходимо проверить ReceiveLength(Сколько можно прочитать) и когда CanRead=False читать не нужно, а то будет как у тебя в TelnetSocket!
Страницы: 1 2 вся ветка
Текущий архив: 2011.10.02;
Скачать: CL | DM;
Память: 0.58 MB
Время: 0.01 c