在客户端建立一个socket并bind之后,启动一个线程函数,在线程之内调用recv函数,如果服务器没有发送数据,此时这个线程会进入阻塞状态,我的问题是此时还可不可以针对这个socket调用send方法?(在java中,可以对一个socket调用getInputStream和getOutputStream获取输入流和输出流,对这两个流的操作互不影响。但在delphi中,针对一个socket创建了两个TWinSocketStream,当一个流进入阻塞状态时,令一个流似乎也不再可用,请问有无解决办法?因为我想在接收数据的同时仍然向服务器发送数据)
谢谢

解决方案 »

  1.   

    http://idoor.xiloo.com 有篇文章,《TCP/IP Winsock编程要点》里面讲了同时收发方法。
      

  2.   

    非常感谢蒋天书。那么我现在是否可以确认其实socket在同一时间内其实是单向的。也就是说,如果它在读数据(即正在调用recv),那么在读数据的操作完成之前,就不能再调用写数据的方法(send)?
      

  3.   

    似乎不行啊(但在java里面确实是可以),如果你懂delphi,可以看看下面的代码。如果你有别的例子,发给我也行。我写了下面的程序,但如果n := s_in.Read(buf[1],bufferSize);正在等待数据,那么
    procedure TWorker.sendToServer(msg: String);
    begin
      msg := msg+ EOL;
      s_out.Write(msg[1],Length(msg));
    end;
    就会也进入等待状态,这是为什么?
    unit ClientUnit;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ScktComp, ConstUnit;type
      TWorker = class;
      TForm2 = class(TForm)
        mMsg: TMemo;
        Edit1: TEdit;
        btnSend: TButton;
        procedure btnSendClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
        worker:TWorker;
      public
        { Public declarations }
        procedure printMessage(msg:string);
      end;  TWorker = class(TThread)
      private
        OutSocket,ClientSocket: TClientSocket;
        socket:TCustomWinSocket;
        s_in : TWinSocketStream;
        s_out:TWinSocketStream;
      public
        procedure sendToServer(msg:String);
        procedure Execute;override;
        procedure Test;
        constructor Create(createSuspended:boolean);
        destructor Destroy;override;
      end;
    var
      Form2: TForm2;implementation{$R *.dfm}{ TWorker }constructor TWorker.Create(createSuspended: boolean);
    begin
      ClientSocket := TClientSocket.Create(nil);
      ClientSocket.Address := '10.8.6.70';
      ClientSocket.Port := 8000;
      ClientSocket.ClientType := ctBlocking;
      ClientSocket.Active := true;
      {
      OutSocket := TClientSocket.Create(nil);
      outSocket.Address := '10.8.6.70';
      OutSocket.Port := 8000;
      OutSocket.ClientType := ctBlocking;
      OutSocket.Active := true;
      }
      socket := ClientSocket.socket;
      self.FreeOnTerminate := true;
      s_in := TWinSocketStream.Create(socket,60000);
      s_out := TWinSocketStream.Create(socket,60000);
      inherited Create(createSuspended);
    end;destructor TWorker.Destroy;
    begin
      s_in.Free;
      s_out.Free;
      ClientSocket.Close;
      ClientSocket.Free;
      //OutSocket.Close;
      //OutSocket.Free;
    end;procedure TWorker.Execute;
    var
      buf,msg:string;
      n:integer;
    begin
      //inherited;
      //Form2.PrintMessage('Start Listening from server');
      sendToServer('I have connected to u');
      while socket.Connected do
      begin
        msg := '';
        repeat
          buf := '';
          SetLength(buf,bufferSize);
          n := s_in.Read(buf[1],bufferSize);
          form2.printMessage('read bytes='+IntToStr(n));
          if n = 0 then break;
          SetLength(buf,n);
          //form2.printMessage('+++++++++++++buf is '+buf);
          msg := msg + buf;
        until(Pos(EOL,buf)>0);    if msg <> '' then form2.printMessage('=========='+msg);
        form2.printMessage('.........IDLE');
        self.sendToServer('test');
        //sleep(1300);
      end;
    end;procedure TWorker.sendToServer(msg: String);
    begin
      msg := msg+ EOL;
      s_out.Write(msg[1],Length(msg));
    end;procedure TWorker.Test;
    begin
      form2.printMessage('TWorker::Test');
    end;{ TForm2 }procedure TForm2.printMessage(msg: string);
    begin
      mMsg.Lines.Add(msg);
    end;procedure TForm2.btnSendClick(Sender: TObject);
    begin
      worker.sendToServer(Edit1.Text);
      //worker.Test;
    end;procedure TForm2.FormCreate(Sender: TObject);
    var
      test:string;
    begin
      worker := TWorker.Create(False);
      //worker.sendToServer(test);
      //worker.Resume;
    end;end.
      

  4.   

    这个问题已经找到答案。winsock的send和recv是双向的,但delphi中确实有上述问题,可能是delphi的控件有一些问题。