Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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
4-1251086922
GrayFace
2009-08-24 08:08
2011.10.02
Как бы перевести код клавиши в символ с учетом языка?


2-1307895125
Leon-Z
2011-06-12 20:12
2011.10.02
Предупреждение компилятора.


15-1307485149
Marser
2011-06-08 02:19
2011.10.02
А я вот во Львов переехал...


15-1307987145
Andrey K
2011-06-13 21:45
2011.10.02
Караул. Не запустить Delphi


2-1307635571
Leon-Z
2011-06-09 20:06
2011.10.02
БД в виде *.xml файлов.