现在要做一个关于C/S的程序.因为服务器要判断客户机的请求然后做出应答,而客户机也要在收到服务器的应答之后再发出相应的请求.想请教一下在这种情况下,ServerSocket控件和ClientSocket控件应该在什么时候读和写?在哪个事件中?

解决方案 »

  1.   

    非阻塞下的方式我刚试了一下,但没有试成功,给你看看阻塞方式的:
    http://expert.csdn.net/Expert/topic/1093/1093894.xml?temp=2.544582E-03阻塞方式加上线程,因为是应答过程,所以Client要等待Server的响应,所以应该在线程中来实现,其中重要的功能就是winsock.Select函数了,其实的就是自已定义的,你先看看.还有这是我刚写的非阻塞下的代码,但是不正确,但意思是相同的.你看看.
    //clientMain.pas
    unit ClientMain;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ExtCtrls, ScktComp;type
      TForm2 = class(TForm)
        RadioGroup1: TRadioGroup;
        CommandButton: TButton;
        ClientSocket1: TClientSocket;
        HostEdit: TEdit;
        OpenButton: TButton;
        PortEdit: TEdit;
        Memo1: TMemo;
        procedure CommandButtonClick(Sender: TObject);
        procedure OpenButtonClick(Sender: TObject);
        procedure ClientSocket1Connect(Sender: TObject;
          Socket: TCustomWinSocket);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form2: TForm2;implementationuses WinSock;{$R *.dfm}
    const
      SizeInt = SizeOf(Integer);  { Command constant }
      ccMsg = $0001;
      ccASKSome = $0002;
      ccError = $0003;procedure TForm2.CommandButtonClick(Sender: TObject);
    var
      Socket: TCustomWinSocket;  function WaitServer: Boolean;
      var
        FDSet: TFDSet;
        Timeout: TTimeVal;
      begin
        FD_ZERO(FDSet);
        FD_SET(Socket.SocketHandle, FDSet);
        // 5 seconds
        Timeout.tv_sec := 5;
        Timeout.tv_usec := 0;
        // wait for server reponse
        Result := select(0, @FDSet, nil, nil, @Timeout) > 0;
      end;  procedure SendMsgToServer;
      const
        SMsgToServer = 'hello, server';
      var
        Len, ReLen, Command, RetLen: Integer;
      begin
        Len := Length(SMsgToServer);
        Command := ccMsg;
        RetLen := Socket.SendBuf(Command, SizeInt);
        if RetLen <> SizeInt then
          raise ESocketError.Create('socket Write error');
        RetLen := Socket.SendBuf(Len, SizeInt);
        if RetLen <> SizeInt then
          raise ESocketError.Create('socket Write error');
        RetLen := Socket.SendBuf(PChar(SMsgToServer)^, Len);
        if RetLen <> Len then
          raise ESocketError.Create('socket Write error');
        if WaitServer then
        begin
          RetLen := Socket.ReceiveBuf(Command, SizeInt);
          if (RetLen <> SizeInt) or (Command <> ccMsg) then
            raise Exception.Create('server reponse command is error');
          RetLen := Socket.ReceiveBuf(ReLen, SizeInt);
          if (RetLen <> SizeInt) or (ReLen <> Len) then
            raise Exception.Create('server response length is error');
          Memo1.Lines.Add('msg is send to server');
        end
        else
          raise ESocketError.Create('Server not reponse or timeout');
      end;  //procedure Send
    begin
      if not ClientSocket1.Active then
        raise ESocketError.Create('Socket not open');
      Socket := ClientSocket1.Socket;
      case RadioGroup1.ItemIndex of
        0: SendMsgToServer;
        1: ;
        2: ;
      else
        ;
      end;
    end;procedure TForm2.OpenButtonClick(Sender: TObject);
    begin
      with ClientSocket1 do
      begin
        if Active then Close;
        Sleep(10);
        Port := StrToInt(PortEdit.Text);
        Host := HostEdit.Text;
        Open;
      end;
    end;procedure TForm2.ClientSocket1Connect(Sender: TObject;
      Socket: TCustomWinSocket);
    begin
      Memo1.Lines.Add('is connect to server, you can send command')
    end;end.//clientMain.dfm
    object Form2: TForm2
      Left = 192
      Top = 103
      Width = 544
      Height = 375
      Caption = 'Form2'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object RadioGroup1: TRadioGroup
        Left = 240
        Top = 160
        Width = 241
        Height = 105
        Caption = 'RadioGroup1'
        ItemIndex = 0
        Items.Strings = (
          'Some message to Server'
          'Ask Server and Wait...'
          'Error Request')
        TabOrder = 0
      end
      object CommandButton: TButton
        Left = 240
        Top = 280
        Width = 121
        Height = 25
        Caption = 'Send Command'
        TabOrder = 1
        OnClick = CommandButtonClick
      end
      object HostEdit: TEdit
        Left = 248
        Top = 48
        Width = 121
        Height = 21
        TabOrder = 2
        Text = '127.0.0.1'
      end
      object OpenButton: TButton
        Left = 248
        Top = 80
        Width = 113
        Height = 25
        Caption = 'Connect to Host'
        TabOrder = 3
        OnClick = OpenButtonClick
      end
      object PortEdit: TEdit
        Left = 248
        Top = 16
        Width = 121
        Height = 21
        TabOrder = 4
        Text = '211'
      end
      object Memo1: TMemo
        Left = 32
        Top = 16
        Width = 185
        Height = 297
        Lines.Strings = (
          'Memo1')
        TabOrder = 5
      end
      object ClientSocket1: TClientSocket
        Active = False
        Address = '127.0.0.1'
        ClientType = ctNonBlocking
        Port = 0
        OnConnect = ClientSocket1Connect
        Left = 368
        Top = 280
      end
    end
      

  2.   

    //serverMain.pas
    unit serverMain;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ScktComp, StdCtrls;type
      TForm1 = class(TForm)
        ServerSocket1: TServerSocket;
        Memo1: TMemo;
        procedure ServerSocket1ClientRead(Sender: TObject;
          Socket: TCustomWinSocket);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}const
      SizeInt = SizeOf(Integer);  { Command constant }
      ccMsg = $0001;
      ccASKSome = $0002;
      ccError = $0003;  SMsgToClient = 'yes, you can.';
      SMsgError = 'Error Message';procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
      Socket: TCustomWinSocket);
    var
      P, Data: PChar;
      RetLen, Command, StreamLen, Count: Integer;
    begin
      RetLen := Socket.ReceiveLength;
      if RetLen = 0 then Exit;
      RetLen := Socket.ReceiveBuf(Command, SizeInt);
      if RetLen <> SizeInt then
        raise ESocketError.Create('Socket read error');
      RetLen := Socket.ReceiveBuf(Count, SizeInt);
      if RetLen <> SizeInt then
        raise ESocketError.Create('Socket read error');
      GetMem(Data, Count);
      try
        P := Data;
        case Command of
          ccMsg:
          begin
            StreamLen := Count;
            while Count > 0 do
            begin
              RetLen := Socket.ReceiveBuf(P^, Count);
              if RetLen > 0 then
              begin
                Inc(Integer(P), RetLen);
                Dec(Count, RetLen);
              end;
            end;
            Socket.SendBuf(Command, SizeInt);
            Socket.SendBuf(StreamLen, SizeInt);
            Memo1.Lines.Add(Format('message: %s', [Data]));
          end;
          ccASKSome:
          begin
            Command := ccASKSome;
            Count := Length(SMsgToClient);
            Socket.SendBuf(Command, SizeInt);
            Socket.SendBuf(Count, SizeInt);
            Socket.SendBuf(PChar(SMsgToClient)^, Count);
            Memo1.Lines.Add('Response client Ask some.')
          end;
        else
          Command := ccError;
          Count := Length(SMsgError);
          Socket.SendBuf(Command, SizeInt);
          Socket.SendBuf(Count, SizeInt);
          Socket.SendBuf(PChar(SMsgError)^, Count);
          Memo1.Lines.Add('Client request is error');
        end;
      finally
        FreeMem(Data);
      end;
    end;end.
    //serverMain.dfm
    object Form1: TForm1
      Left = 192
      Top = 103
      Width = 544
      Height = 375
      Caption = 'Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object Memo1: TMemo
        Left = 272
        Top = 32
        Width = 241
        Height = 305
        Lines.Strings = (
          'Memo1')
        TabOrder = 0
      end
      object ServerSocket1: TServerSocket
        Active = True
        Port = 211
        ServerType = stNonBlocking
        OnClientRead = ServerSocket1ClientRead
        Left = 208
        Top = 96
      end
    end