我的serversocket多线程老是重复接受数据,客户端发送数据后,服务器端线程接受后,老是重复接受感觉客户端一直在发送一样,但是如果服务器端改为非阻塞的就只有一次,我问了他们的工程师,说是本来也只发了一次,郁闷惨了,我把代码贴出来,大家看看怎么回事 
procedure TserverThread.ClientExecute;
var
ReceiveBuffer:Array[0..300] Of byte;//16进制
InputStream:TWinSocketStream;
str,strData:string;
len,i:integer;
sStream:TWinSocketStream;
sBuffer:array[0..3071] of byte;
Begin
    //获取和操作命令,直到连接断开或者线程终止
    while not Terminated and ClientSocket.Connected do
    Begin
        Try
            strdata:='';
            len:=ClientSocket.ReceiveLength;
            sStream:= TWinSocketStream.Create(ClientSocket,3000);
            try //填充SBuffer数组
                FillChar(sBuffer,sizeof(sbuffer),0);
                //延迟时间60秒
                If sStream.WaitForData(3000) then
                Begin
                    If sStream.Read(sBuffer,sizeof(sbuffer))=0 then
                    begin
                         FillChar(sBuffer,sizeof(sbuffer),0);
                         sBuffer[0]:=$C0;
                         sBuffer[1]:=$00;
                         sBuffer[2]:=$08;
                         sBuffer[3]:=$21;
                         ClientSocket.Close;
                    end
                    else
                    if len>0 then
                    begin
                          for i:=0 to len-1 do
                          begin
                                str:=inttohex(sBuffer[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);
                           FillChar(sBuffer,sizeof(sbuffer),0);
                           sBuffer[0]:=$C0;
                           sBuffer[1]:=$00;
                           sBuffer[2]:=$08;
                           sBuffer[3]:=$21;
                           ClientSocket.SendBuf(ReceiveBuffer,8);
                           clientsocket.Close;
                    end;
                end
                else ClientSocket.Close;
            except
            HandleException;
            end;
        Finally
        sStream.Free;
        end;
    end;
End;

解决方案 »

  1.   

    ClientSocket.Close; 
    后再加个
    break;
    会不会好一点?
      

  2.   

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

  3.   

    If sStream.Read(sBuffer,sizeof(sbuffer))=0 then //这行有错
    begin
        FillChar(sBuffer,sizeof(sbuffer),0);
        sBuffer[0]:=$C0;
        sBuffer[1]:=$00;
        sBuffer[2]:=$08;
        sBuffer[3]:=$21;
        ClientSocket.Close;
    end
    else
    if len>0 then //影响到这条判断语句
        //因为如果连接关闭后,实际接收长度为0,但是你的Len值没有被赋值为0,所以会反复执行判断条件中的语句
    begin应改为
    Len:=sStream.Read(sBuffer,sizeof(sbuffer));
    if Len=0 then //如果本次读取的数据长度为0,则说明连接关闭了
    begin
        FillChar(sBuffer,sizeof(sbuffer),0);
        sBuffer[0]:=$C0;
        sBuffer[1]:=$00;
        sBuffer[2]:=$08;
        sBuffer[3]:=$21;
        ClientSocket.Close;
    end
    else
    if len>0 then 
    begin
      
      

  4.   

    现在是当客户端链接后,就生成了一个线程,只要客户端或者服务端不关闭这个soket那么以后一直用这个socket来通讯,我不知道Terminated 什么时候才算结束呢,我的意思是每个线程结束后socket不关闭,不知道咋个整哦
      

  5.   


    每个连接建立一个线程通讯,没什么问题啊,当连接存在的时候线程不需要Terminate
      

  6.   

    C#的,刚刚完成的,自己看吧
     private void SocketStart()
            {         
                try
                {
                    IPAddress localAddr = IPAddress.Parse(serverIP);
                    GpsListener = new TcpListener(localAddr, serverPort); // TcpListener Listener = new TcpListener(port);
                   
                    GpsListener.Start();                                  // Start listening for client requests.
                    ConnectOK = 0;
                    myForm.showInfo("***** 监听软件已经启动..... *****\r\n\r\n");
                    while (true) {
                        try
                        {
                            GpsSocket = GpsListener.AcceptSocket();
                            GPSServiceThread = new Thread(new ThreadStart(ServiceClient));
                            GPSServiceThread.Start();
                            Thread.Sleep(5); 
                        }
                        catch 
                        {
                        }
     private void ServiceClient()
            {
                try
                {
                    //string Myip = "";
                    string MyPort = "";
                    string path = Application.StartupPath + @"\GpsSocketInfo.txt";
                    Socket ThisTempSocket = GpsSocket;
                    bool keepalive = true;   
                    while (true)
                    {
                        Byte[] GpsBuffer = new Byte[1024];
                        int bufLen = 0;// MessageBox.Show(myForm.Test());
                        try
                        {
                            bufLen = ThisTempSocket.Available;//获取已经从网络接收且可供读取的数据量。
                            ThisTempSocket.Receive(GpsBuffer, 0, bufLen, SocketFlags.None);//将数据放在buffer里
                            if (bufLen == 0)
                                continue;
                        }
                        catch
                        {
                            return;
                        }                    int cmd = 0x83;
                        int cmdws = 0x4D;
                        if (Convert.ToInt32(GpsBuffer[21]) == cmd)
                        {
                            int   year = Convert.ToInt32(GpsBuffer[28]);
                            if ((year == 0))//如果接受到数据是0000则continue
                            {
                                myForm.showInfo("\r\n" + "开始接受信息!" + "\r\n");
                                continue;
                            }                        ConvertBufferCmdToStrToSend(GpsBuffer);                  
                            continue;                    }                    if (Convert.ToInt32(GpsBuffer[21]) == cmdws)
                        {
                            setConnectOK(ThisTempSocket, GpsBuffer);
                            Sendmsg(GpsBuffer);
                            continue;
                        }                    string cmdstr = System.Text.Encoding.ASCII.GetString(GpsBuffer);
                        if (cmdstr.IndexOf("policy-file") > 0)
                        {
                            string s = "<?xml version=\"1.0\"?><cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>\0";
                            Byte[] b = System.Text.Encoding.Default.GetBytes(s);
                            ThisTempSocket.Send(b);
                            continue;
                        }
                        cmdstr = cmdstr.Substring(0, 2);                    if (cmdstr.Equals("CC"))//客户端的机子发送请求
                        {
                            CCresponsion(ThisTempSocket);
                            continue;
                        }                  
                       
                        Thread.Sleep(5);
                    }
                    ThisTempSocket.Close();
                }
                catch (Exception ex)
                {
                    myForm.showInfo("\r\n" + ex.Message.ToString() + "\r\n");
                }        }
      

  7.   

    断了你这里是判断不出来的,需要这样
    While (Not Terminated)And FOwner.Active Do
      begin
        nTickCount := GetTickCount;
        If FOwner.FSockStream.WaitForData(FOwner.ReadTimeout) Then // 如果有数据到来
          If Not Terminated Then
            Repeat
              Begin
                BytesDone:= FOwner.FSockStream.Read(FReadBuf, 65536);
                // 可能错误
                If BytesDone = 0 Then
                begin
                  if (GetTickCount - nTickCount)<FOwner.ReadTimeout then
                  begin
                    FOwner.Close;
                    FOwner.FWriteThread.udSuspend;
                    //重连
                    FOwner.FWorkThread.FReConnectEvent.SetEvent;
                    //休眠自己
                    Suspend;
                  end;
                end
      

  8.   

    发送前:ClientSocket.Lock;发送后:ClientSocket.Unlock;你自己试一下。
      

  9.   

    ClientSocket的lock和unlock虽然很老土,但是很适用的
      

  10.   


    把线程去掉,循环2次,for i=0 to 1 do
    begin
      通讯过程
    end;
    调试下通讯过程。就知道对方到底发了几次