Конференция "Сети" » Сдвиг данных TcpClient при задержках чтения буфера [WinXP]
 
  • FireMan_Alexey © (28.09.11 12:48) [20]
    Пример использования.

    Sock.Host:='127.0.0.1';
    Sock.Port:=8080;
    If Not Sock.Connect Then
     Begin
          ShowMessage(IntToStr(Sock.Error));
          Exit;
     End;
    While (not Terminated)and(Not Sock.Disconnected) do
     Begin
       Sock.GetStatus;
       If Sock.ErrorPresent Then {obrabativaem oshibku}
       If Sock.CanRead Then  Size:=Sock.ReceiveLength; //Potom chitaem -> Sock.Read
       If Sock.CanWrite Then //Pichem
     End;
    Sock.Close;
  • FireMan_Alexey © (28.09.11 12:49) [21]
    Сам модуль.

    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;
     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.
  • Alik (28.09.11 20:38) [22]
    Спасибо всем, буду пробовать!
 
Конференция "Сети" » Сдвиг данных TcpClient при задержках чтения буфера [WinXP]
Есть новые Нет новых   [134436   +21][b:0][p:0]