TCP服务器导致MAX CPU使用

问题描述:

我写这个TCP通信库。问题在于。当客户端连接时。导致CPU占用提升到最大....这会导致其他应用程序变慢......TCP服务器导致MAX CPU使用

请看看代码并纠正我哪里做错了..

我的TCP的主代码图书馆是

TCP服务器类

public class TCPServerEndPoint : ICommunication 
    { 

     private string channelName; 

     private string localIP; 

     private int localPort; 

     private string remoteIP; 

     private int remotePort; 

     private TcpListener tcpListenter; 

     /// <summary> 
     /// Accept the incomming connection and pass it to a thread to handle communication. 
     /// </summary> 
     private TCPServerWorker worker; 

     /// <summary> 
     /// List of threads created for connected clients. 
     /// </summary> 
     List<TCPServerWorker> workerThreads; 

     /// <summary> 
     /// Thread to keep listening process in seperate thread. 
     /// </summary> 
     private Thread serverThread; 

     /// <summary> 
     /// Flag to keep status of Endpoint. 
     /// </summary> 
     private bool keepRunning; 

     public TCPServerEndPoint() 
     { 
      this.keepRunning = false; 
      Guid guid = Guid.NewGuid(); 
      channelName = guid.ToString(); 
      workerThreads = new List<TCPServerWorker>(); 
     } 

     public TCPServerEndPoint(string localIP, int localPort, string remoteIP, int remotePort) 
     { 
      this.localIP = localIP; 
      this.localPort = localPort; 
      this.remoteIP = remoteIP; 
      this.remotePort = remotePort; 

      workerThreads = new List<TCPServerWorker>(); 

      this.keepRunning = false; 
     }   

     public event EventHandler<CommEventArgs> OnCommReceive; 


     public int CommStart() 
     { 
      if (this.IsStarted == true) 
      { 
       Console.WriteLine("TCP Server is already running"); 
       return -1; 
      } 

      serverThread = new Thread(new ThreadStart(StartListening)); 
      serverThread.IsBackground = true; 
      serverThread.Start(); 

      return 0; 
     } 

     private void StartListening() 
     { 
      try 
      { 
       IPAddress localAddress = IPAddress.Parse(this.localIP); 
       tcpListenter = new TcpListener(localAddress, this.localPort); 
       tcpListenter.Start(); 
       Console.WriteLine("TCP Server started"); 
       Console.WriteLine("Server is listening on port : {0}", this.localPort); 

       this.keepRunning = true; 

       // look for incomming connections 
       while (this.keepRunning) 
       { 
        // connection received 
        TcpClient client = tcpListenter.AcceptTcpClient(); 

        // create a new WorkerThread and pass the connected client to handle. 
        worker = new TCPServerWorker(client); 
        worker.dataReceived += new EventHandler<CommEventArgs>(worker_dataReceived); 
        workerThreads.Add(worker); 
        worker.Start(); 
       } 

       tcpListenter.Stop(); 
       Console.WriteLine("TCP Server stopped"); 
       this.keepRunning = false; 
      } 
      catch 
      {     
       return; 
      } 
     } 

     void worker_dataReceived(object sender, CommEventArgs e) 
     { 
      if (this.OnCommReceive != null) 
      { 
       e.commChannel = this; 
       this.OnCommReceive(this, e); 
      } 
     } 


     public int CommStop() 
     { 
      if (this.IsStarted == false) 
       return -1; 

      // Close all worker threads created for connected clients. 
      foreach (TCPServerWorker item in workerThreads) 
      { 
       item.KeepRunning = false; 
      } 

      // break the listening loop 
      this.keepRunning = false; 

      // clear the worker thread list 
      workerThreads.Clear(); 

      // force server to receive message to break while(keepRunning) loop 
      byte[] data = new byte[4]; 
      IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(this.localIP), localPort); 
      Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
      tcpClient.Connect(ipEndPoint); 
      tcpClient.SendTo(data, ipEndPoint); 
      tcpClient.Close(); 

      return 0; 
     } 


     public int CommSend(CommEventArgs obj) 
     { 
      obj.destAddress = this.remoteIP; 
      obj.destPort = this.remotePort; 
      return CommSendTo(obj); 
     } 


     public int CommSendTo(CommEventArgs obj) 
     { 
      int n; 
      byte[] buf; 
      try 
      { 
       IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Parse(obj.destAddress), obj.destPort); 
       buf = (byte[])obj.data; 

       Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
       tcpClient.Connect(ipEndPoint); 
       n = tcpClient.SendTo(buf, ipEndPoint); 
       tcpClient.Close(); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Exception :: {0}", ex.Message); 
       return -1; 
      } 
      if (n == buf.Length) 
      { 
       if (OnCommSendComplete != null) 
       { 
        OnCommSendComplete(this, obj); 
       }    
       Console.WriteLine("Sent {0} bytes to {1}:{2}", n, obj.destAddress, obj.destPort); 
      } 
      else 
      {    
       return -1; 
      } 

      return n; 
     } 
    } 
} 

TCPServerWorker.cs

class TCPServerWorker 
    { 

     private TcpClient client; 


     private bool keepRunning; 


     public event EventHandler<CommEventArgs> dataReceived; 


     private const int MAX_TCP_DATA = 64000; 


     public bool KeepRunning 
     { 
      get 
      { 
       return this.keepRunning; 
      } 
      set 
      { 
       this.keepRunning = value; 
      } 
     } 

     public TCPServerWorker(TcpClient client) 
     { 
      this.client = client; 
      this.keepRunning = false; 
     } 

     public void Start() 
     { 
      Thread thread = new Thread(new ThreadStart(Process)); 
      thread.IsBackground = true; 
      thread.Start(); 
     } 

     private void Process() 
     { 
      if (client.Connected == true) 
      { 
       Console.WriteLine("Client connected :: {0}", client.Client.RemoteEndPoint); 
       this.keepRunning = true; 

       while (this.keepRunning) 
       { 
// in my view. here is the main problem. this loop run for infinite time and causes CPU to reach at 100 
        byte[] buffer = new byte[MAX_TCP_DATA];      
        NetworkStream stream = client.GetStream(); 
        StreamWriter writer = new StreamWriter(client.GetStream()); 

        if (stream.DataAvailable == true) 
        { 
         int receivedBytesCount = stream.Read(buffer, 0, buffer.Length); 

         byte[] receivedBuffer = new byte[receivedBytesCount]; 

         Array.Copy(buffer, receivedBuffer, receivedBytesCount); 

         String msg = Encoding.UTF8.GetString(receivedBuffer); 
         Console.WriteLine("Received MSG ::: " + msg); 

         writer.WriteLine("Server : Received {0} bytes", receivedBytesCount); 

         CommEventArgs comEventArg = new CommEventArgs(); 
         comEventArg.data = (byte[])receivedBuffer; 
         IPEndPoint remoteIPEndPoint = (IPEndPoint)client.Client.RemoteEndPoint; 

         comEventArg.srcAddress = remoteIPEndPoint.Address.ToString(); 
         comEventArg.srcPort = remoteIPEndPoint.Port; 
         comEventArg.length = receivedBytesCount; 
         this.OnDataReceived(comEventArg); 

         writer.Flush(); 
        } 
       } 
       client.Close();     
      } 
     } 

     protected void OnDataReceived(CommEventArgs e) 
     { 
      if (this.dataReceived != null) 
      { 
       this.dataReceived(this, e); 
      } 
     } 
    } 
} 

我修改TCPServerWorker的加工方法后解决了问题。 CS

这里的变化

private void Process() 
     { 
      if (client.Connected == true) 
      { 
       Console.WriteLine("Client connected :: {0}", client.Client.RemoteEndPoint); 
       Byte[] bytes = new Byte[MAX_TCP_DATA]; 
       String data = null; 
       NetworkStream stream = client.GetStream(); 

       int i; 

       try 
       { 
        // Loop to receive all the data sent by the client. 
        while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) 
        { 
         // bytes contains received data in byte[]. 
         // Translate data bytes to a UTF-8 string. 
         byte[] receivedBuffer = new byte[i]; 
         Array.Copy(bytes, receivedBuffer, i); 

         data = System.Text.Encoding.UTF8.GetString(receivedBuffer); 
         Console.WriteLine("Received MSG ::: " + data); 

         // Process the data sent by the client. 

         byte[] msg = System.Text.Encoding.UTF8.GetBytes(data); 

         // Send back a response. 
         stream.Write(msg, 0, msg.Length); 

         CommEventArgs comEventArg = new CommEventArgs(); 
         comEventArg.data = receivedBuffer; 
         IPEndPoint remoteIPEndPoint = (IPEndPoint)client.Client.RemoteEndPoint; 
         comEventArg.srcAddress = remoteIPEndPoint.Address.ToString(); 
         comEventArg.srcPort = remoteIPEndPoint.Port; 
         comEventArg.length = i; 
         this.OnDataReceived(comEventArg); 
        } 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine("Exception : " + ex.Message); 
       } 
       finally 
       { 
        client.Close(); 
       }     
      } 
     } 

有一点要注意的是,你从来没有SET IsStarted ..你只能得到它._。也许你产生了数百个线程= /我正在谈论TCPServerEndPoint类=/

+0

如果在IsStarted中保持运行,我会获得价值 – Mohsan 2010-02-25 08:28:20

+0

请重新说明您刚刚陈述的内容。我不是想成为一个语法警察或任何其他的人,因为我相信语言是为了交流,而不是为了“聪明”......但我不能理解你说的话。对不起,如果我听起来像我正在拖动。 – Warty 2010-02-25 08:29:34

+0

你说,“你从来没有SET IsStarted ..你只得到它”,所以在回复我说。我在IsSrated中使用keepRunning(变量)的值。 – Mohsan 2010-02-25 08:36:34

是的,你正忙着等待连接。我不知道套接字编程,所以我不能告诉你详细信息,但是你需要做的是等待使用阻塞系统调用的连接。

+0

AcceptTcpClient阻塞,直到客户端进入,所以不应该是他的程序占用处理器的原因 – Warty 2010-02-25 08:23:22

您使用非阻塞I/O导致一个循环(至少)在客户端

while (this.keepRunning) {...} 

这是由忙等待消耗所有的CPU资源。

你应该考虑在第一句话使用阻塞I/O或Socket.Select

here

详情约select