客户断clientsocket,阻塞模式,服务端serversocket 线程阻塞模式
客户端:
procedure TForm1.RzBitBtn5Click(Sender: TObject);
var i,len:integer;
    strData,bmstr: string;
    buf:  Pchar;
begin
       bmstr:='4343434343433ewedsfdewewreewew323232ewds3es3de3ds3ds3es3evvvvvvvvvvvvvvxxcfsgdd***';
       len:=length(bmstr);
       buf :=allocmem(len);
       ClientSocket1.Socket.SendBuf(buf^,len);
end;
服务器端:
数据来时生成线程
procedure TForm1.TcpServer1GetThread(Sender: TObject;
  ClientSocket: TServerClientWinSocket;
  var SocketThread: TServerClientThread);
begin
      SocketThread :=TserverThread.Create(false,ClientSocket);
end;线程的执行
procedure TserverThread.ClientExecute;
var
ReceiveBuffer:Array Of Char;
ReceiveD:TMemoryStream;
InputStream:TWinSocketStream;
OutputStream:TWinSocketStream;
buf:pchar;
bmstr,strData:string;
len,i:integer;
begin
    while not Terminated and ClientSocket.Connected do
    begin
    Try
        InputStream:=TWinSocketStream.Create(ClientSocket,10000);
        Try
            ReceiveD:=TMemoryStream.Create;
            len:=clientsocket.ReceiveLength;
            setlength(ReceiveBuffer,len);
            FillChar(ReceiveBuffer, sizeof(ReceiveBuffer),0);
            While InputStream.WaitForData(10000)   do
            begin
                if InputStream.Read(ReceiveBuffer,SizeOf(ReceiveBuffer))=0 then
                begin//接受数据完毕,相链接的socket回发数据
                //clientsocket.SendBuf(buf^,length(bmstr));
                ClientSocket.Close;
                end
                else
                begin --此处应该怎么写啊,我是直接读到内存流中了,感觉不对
                     inputstream.Read(ReceiveD,len);
                end;
            end;
        Finally
            //form1.Memo1.Lines.LoadFromStream(InputStream);
            InputStream.Free;
            ClientSocket.Close;
        End;
    Except
    End;
    end;
end;
问题:不知道怎么接受数据,线程有点晕,半管水哈,
而且把接受的数据显示到memo控件中

解决方案 »

  1.   

    这个是做的接口程序,对方用soket阻塞模式发送数据过来,可能会产生一对多的并发数据,所以考虑用多线程,
    但是对这个东西不太熟悉啊
      

  2.   

    if InputStream.Read(ReceiveBuffer,SizeOf(ReceiveBuffer))=0
    这句话是不是表示已经读取数据完毕,读取的数据是存在ReceiveBuffer中的吗?
    如果是的话我要将它显示在form上的memo中应该怎么写啊?
    或者说我要将ReceiveBuffer中的数据放在一个字符串中应该怎么写?
      

  3.   

    非阻塞好,你要阻塞的就用TIDTCPSERVER
      

  4.   

    代码改变如下:
    procedure TserverThread.ClientExecute;
    var ...
    begin
     while not Terminated and ClientSocket.Connected do
        begin
        Try
             strdata:='';
             len:= ClientSocket.ReceiveLength;
             if len>0 then
             begin
                   buf :=allocmem(len);
                   ClientSocket.ReceiveBuf(buf^,len);
                   for i:=0 to len-1 do
                   strData:=strData+Format('%X',[Ord(pChar(buf+i)^)])+' ';
                   if strdata<>'' then
                   begin
                        memo1.Lines.Add(strdata);
                        bmstr:='C00D1121';
                        len:=length(bmstr);
                        buf :=allocmem(len);
                        clientsocket.SendBuf(buf^,len);
                   end;
             end else clientsocket.close;
    end;
    服务器端不做超时设置,让clientsocket一直跟客户端链接,客户端有超时设置,当客户端断开后,客户服务端的socket也断开,线程结束,问题是这样做有没有什么问题啊?
      

  5.   



      Important: Methods and properties of objects in visual components can only be
      used in a method called using Synchronize, for example,      Synchronize(UpdateCaption);  and UpdateCaption could look like,    procedure dsddfdsf.UpdateCaption;
        begin
          Form1.Caption := 'Updated in a thread';
        end;    or    Synchronize(
          procedure
          begin
            Form1.Caption := 'Updated in thread via an anonymous method'
          end
          )
        );  where an anonymous method is passed.  Similarly, the developer can call the Queue method with similar parameters as
      above, instead passing another TThread class as the first parameter, putting
      the calling thread in a queue with the other thread.}注意线程同步的问题
    另: 与vcl交互的地方在Synchronize里写Delphi线程类里有说,如上
      

  6.   

    现在还有一个问题,怎么我用多线程后,客户端发送数据后,服务器端线程接受后,老是重复接受感觉客户端一直在发送一样,但是如果服务器端改为非阻塞的就只有一次,我问了他们的工程师,说是本来也只发了一次,郁闷惨了,我把代码贴出来,大家看看怎么回事
    procedure TserverThread.ClientExecute;
    var
    ReceiveBuffer:Array[0..3071] Of byte;//16进制
    InputStream:TWinSocketStream;
    str,strData:string;
    len,i:integer;
    begin
        while not Terminated and ClientSocket.Connected do
        begin
        try
            InputStream:=TWinSocketStream.Create(ClientSocket,3000);
            FillChar(ReceiveBuffer, sizeof(ReceiveBuffer),0);
            try
                  if InputStream.WaitForData(3000) then
                  begin
                      strdata:='';
                      len:=ClientSocket.ReceiveLength;
                      if InputStream.Read(ReceiveBuffer,SizeOf(ReceiveBuffer))=0 then
                      begin
                           ReceiveBuffer[0]:=$C0;
                           ReceiveBuffer[1]:=$00;
                           ReceiveBuffer[2]:=$08;
                           ReceiveBuffer[3]:=$21;
                           ClientSocket.SendBuf(ReceiveBuffer,8);
                           clientsocket.Close;
                      end;
                      if len>0 then
                      begin
                            for i:=0 to len-1 do
                            begin
                                  str:=inttohex(ReceiveBuffer[i],2);
                                  strdata:=strdata+str+' ';
                                  case i of
                                       0:memo1.lines.Add('包的检测码:'+str);
                                       2:memo1.lines.Add('包的大小:'+str);
                                       3:memo1.Lines.Add('功能码:'+str);
                                  end;
                             end;
                             memo1.lines.Add(strdata);
                             ReceiveBuffer[0]:=$C0;
                             ReceiveBuffer[1]:=$00;
                             ReceiveBuffer[2]:=$08;
                             ReceiveBuffer[3]:=$21;
                             ClientSocket.SendBuf(ReceiveBuffer,8);
                             clientsocket.Close;
                       end;
                  end
                  else clientsocket.Close;
            finally
                  InputStream.Free;
                  clientsocket.Close;
            end;
        except
        end;
        end;
    end;
      

  7.   

    你有没有修改过SOCKET的属性,默认读取后应该就会从接收缓冲区删除的
      

  8.   

    shuihan20e:没有啊,我用的都是默认的设置啊,快疯了,不知道怎么回事啊
      

  9.   

    我测试了,缓冲区接受数据后是自动清空了,但是
    procedure TForm1.TcpServer1GetThread(Sender: TObject;
      ClientSocket: TServerClientWinSocket;
      var SocketThread: TServerClientThread);
    begin
             SocketThread :=TserverThread.Create(false,ClientSocket,listbox1);end; 
    会不停的被触发,生成线程,但是客户端根本就没有发送任何数据