delphi2007 教程

delphi2007 教程

首页 新随笔 联系 聚合 管理
  1013 Posts :: 0 Stories :: 28 Comments :: 0 Trackbacks
怎样写一个获取数据函数:用TCP/IP通讯,向服务端发送命令,并从服务端获得返回数据. Delphi / Windows SDK/API
http://www.delphi2007.net/DelphiNetwork/html/delphi_20061126110916251.html
我想编写一个函数getDataFormSerevr(command:string):string;  
  函数实现的是:用TCP/IP通讯,向服务端发送command,并从服务端获得返回数据作为函数的值.  
  如何处理等待数据返回的问题?  
  如何解决超时问题?  
  希望高手提供解答.

自己设定一个时间,发出指令后,如果到了时间还是一个字也没收到,就提示挂了,请检查网络!如果已经开始收到了,就搞个进度条出来……让大家请稍侯!

先用timer设置一个时间   一般都是500毫秒就够了   用这个时间来处理返回就够了   如果连接不上的话有个返回值写到线程里面去   如果值为-1就是最大~~

我是在一个函数里实现,怎么能用TIMER呢?

首先,基本不用考虑什么超时问题,因为你是先去连接服务器,然后再用这个函数的,tcp连接后除非发生阻塞,一般不会出现问题,   也可以用异常处理来解决  
  另外,等待数据返回的话,需要用线程来发送和接受

可以使用阻塞通讯模式。下面使我写的同步通讯类单元。  
  unit   RCUnit;  
   
  interface  
  uses   Windows,   SysUtils,   WinSock,   ComObj,   ScktComp,SConnect;  
   
  type  
      ESocketConnectionError   =   class(Exception);  
   
      TQiSocketTransport   =   class(TInterfacedObject)  
      private  
          FEvent:   THandle;  
          FAddress:   string;  
          FHost:   string;  
          FPort:   Integer;  
          FClientSocket:   TClientSocket;  
          FSocket:   TCustomWinSocket;  
      protected  
          {   ITransport   }  
          function   GetWaitEvent:   THandle;   stdcall;  
          function   GetConnected:   Boolean;   stdcall;  
          procedure   SetConnected(Value:   Boolean);   stdcall;  
          function   Receive(WaitForInput:   Boolean;Buffer:Pointer):Integer;   stdcall;  
          function   Send(Buffer:Pointer;Count:Integer):   Integer;   stdcall;  
      public  
          constructor   Create;  
          destructor   Destroy;   override;  
          property   Connected:Boolean   read   GetConnected   write   SetConnected;  
          property   Host:   string   read   FHost   write   FHost;  
          property   Address:   string   read   FAddress   write   FAddress;  
          property   Port:   Integer   read   FPort   write   FPort;  
          property   Socket:   TCustomWinSocket   read   FSocket   write   FSocket;  
      end;  
   
   
  implementation  
   
   
  const  
      SIG_EXCEPTION:Integer=$EEEEEEEE;  
      SIG_OK       :Integer         =$00000000;  
      ESocketReadError           ='Socket   read   error.';  
      ENoAddress           ='No   address.';      
   
  var  
      hWinSock2:   THandle;  
   
      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;  
   
   
  function   CheckSignature(Sig:Integer):Boolean;  
  begin  
      if   Sig=SIG_EXCEPTION   then  
          Raise   Exception.Create('Remote   call   error!')  
      else  
          Result:=True;  
  end;  
   
  {   TQiSocketTransport   }  
   
  constructor   TQiSocketTransport.Create;  
  begin  
      inherited   Create;  
      FEvent   :=   0;  
  end;  
   
  destructor   TQiSocketTransport.Destroy;  
  begin  
      SetConnected(False);  
      inherited   Destroy;  
  end;  
   
  function   TQiSocketTransport.GetWaitEvent:   THandle;  
  begin  
      FEvent   :=   WSACreateEvent;  
      WSAEventSelect(FSocket.SocketHandle,   FEvent,   FD_READ   or   FD_CLOSE);  
      Result   :=   FEvent;  
  end;  
   
  function   TQiSocketTransport.GetConnected:   Boolean;  
  begin  
      Result   :=   (FSocket   <>   nil)   and   (FSocket.Connected);  
  end;  
   
  procedure   TQiSocketTransport.SetConnected(Value:   Boolean);  
  begin  
      if   GetConnected   =   Value   then   Exit;  
      if   Value   then  
      begin  
          if   (FAddress   =   '')   and   (FHost   =   '')   then  
              raise   ESocketConnectionError.Create(ENoAddress);  
          FClientSocket   :=   TClientSocket.Create(nil);  
          FClientSocket.ClientType   :=   ctBlocking;  
          FSocket   :=   FClientSocket.Socket;  
          FClientSocket.Port   :=   FPort;  
          if   FAddress   <>   ''   then  
              FClientSocket.Address   :=   FAddress   else  
              FClientSocket.Host   :=   FHost;  
          FClientSocket.Open;  
      end   else  
      begin  
          if   FSocket   <>   nil   then   FSocket.Close;  
          FSocket   :=   nil;  
          FreeAndNil(FClientSocket);  
          if   FEvent   <>   0   then   WSACloseEvent(FEvent);  
          FEvent   :=   0;  
      end;  
  end;  
   
  function   TQiSocketTransport.Receive(WaitForInput:   Boolean;Buffer:Pointer):Integer;   stdcall;  
   
  var  
      RetLen,   Sig,   StreamLen:   Integer;  
      P:   Pointer;  
      FDSet:   TFDSet;  
      TimeVal:   PTimeVal;  
      RetVal:   Integer;  
      bFirst:   boolean;  
   
  begin  
      Result   :=   0;  
      TimeVal   :=   NIL;  
      FD_ZERO(FDSet);  
      FD_SET(FSocket.SocketHandle,   FDSet);  
      if   not   WaitForInput   then  
      begin  
          New(TimeVal);  
          TimeVal.tv_sec   :=   0;  
          TimeVal.tv_usec   :=   1;  
      end;  
      RetVal   :=   select(0,   @FDSet,   nil,   nil,   TimeVal);  
      if   Assigned(TimeVal)   then  
          FreeMem(TimeVal);  
      if   RetVal   =   SOCKET_ERROR   then  
          raise   ESocketConnectionError.Create(SysErrorMessage(WSAGetLastError));  
      if   (RetVal   =   0)   then   Exit;  
   
      RetLen   :=   FSocket.ReceiveBuf(Sig,   SizeOf(Sig));  
      if   RetLen   <>   SizeOf(Sig)   then  
          raise   ESocketConnectionError.Create(ESocketReadError);  
      CheckSignature(Sig);  
      RetLen   :=   FSocket.ReceiveBuf(StreamLen,   SizeOf(StreamLen));  
      if   RetLen   =   0   then  
          raise   ESocketConnectionError.Create(ESocketReadError);  
      if   RetLen   <>   SizeOf(StreamLen)   then  
          raise   ESocketConnectionError.Create(ESocketReadError);  
      P   :=   Buffer;  
      if   (StreamLen   >   0)   then     WaitForSingleObject(FEvent,   {INFINITE}60000);  
      bFirst   :=   True;  
   
      while   StreamLen   >   0   do  
      begin  
          RetLen   :=   FSocket.ReceiveBuf(P^,   StreamLen);  
          if   RetLen   =   0   then  
          begin  
              if   not   bFirst   then  
                      raise   ESocketConnectionError.Create(ESocketReadError);  
   
              bFirst   :=   False;  
          end;  
   
          if   RetLen   >   0   then  
          begin  
              Dec(StreamLen,   RetLen);  
              Inc(Integer(P),   RetLen);  
          end;  
   
          if   StreamLen   >   0   then  
          begin  
              if   (WaitForSingleObject(FEvent,   {INFINITE}90000)   =   WAIT_OBJECT_0)   then  
              begin  
                  WSAResetEvent(FEvent);  
              end  
              else  
              begin  
                  raise   ESocketConnectionError.Create('Read   Error   Single   Object   Timeout');  
              end;  
          end;  
   
      end;  
      if   StreamLen   <>   0   then  
          raise   ESocketConnectionError.Create(ESocketReadError);  
  end;  
   
  function   TQiSocketTransport.Send(Buffer:Pointer;Count:Integer):   Integer;   stdcall;  
  var  
      Size:Integer;  
  begin  
      Result   :=   0;  
      Size:=Count;  
      if   Size>0   then  
      begin  
          FSocket.SendBuf(Buffer^,   Count);  
      end;  
  end;  
   
  function   LoadWinSock2:   Boolean;  
  const  
      DLLName   =   'ws2_32.dll';  
  begin  
      Result   :=   hWinSock2   >   0;  
      if   Result   then   Exit;  
      hWinSock2   :=   LoadLibrary(PChar(DLLName));  
      Result   :=   hWinSock2   >   0;  
      if   Result   then  
      begin  
          WSACreateEvent   :=   GetProcAddress(hWinSock2,   'WSACreateEvent');  
          WSAResetEvent   :=   GetProcAddress(hWinSock2,   'WSAResetEvent');  
          WSACloseEvent   :=   GetProcAddress(hWinSock2,   'WSACloseEvent');  
          WSAEventSelect   :=   GetProcAddress(hWinSock2,   'WSAEventSelect');  
      end;  
  end;  
   
  initialization  
      LoadWinSock2;  
  end.  
 

你的函数只需类似这样调用即可:  
  ST:TQiSocketTransport  
  ...  
  创建并连接服务器  
  ..  
   
  getDataFormSerevr(command:string):string  
  begin    
      ST.Send....      
      ST.Receive.......  
  end;  
 

posted on 2009-05-26 17:27 delphi2007 阅读(364) 评论(0)  编辑 收藏 引用
只有注册用户登录后才能发表评论。