当前位置:编程学习 > C#/ASP.NET >>

c# socket服务端程序开启一会cpu的占用率达到100%

大侠们帮忙看一下,谢谢,分不是很多,以后有分了再追加给你们,谢谢,下面是我的主要代码:
开启监听:         // UI 线程
            _syncContext = SynchronizationContext.Current;

            //启动后台线程去运行 Socket 服务
            Thread thread = new Thread(new ThreadStart(StartupSocketServer));
            thread.IsBackground = true;
            thread.Start();

 private void StartupSocketServer()
        {
          
            try
            {
                // 初始化 socket , 然后与端口绑定, 然后对端口进行监听
                _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                _listener.NoDelay = true;
                _listener.SendBufferSize = ConstParameter.BUFFER_SIZE;
                _listener.ReceiveBufferSize = ConstParameter.BUFFER_SIZE;
                _listener.Bind(new IPEndPoint(IPAddress.Any, 4515)); // Silverlight 2.0 使用 Socket 只能连接 4502-4534 端口
                _listener.Listen(100);
                while (true)
                {
                    // 重置 ManualResetEvent,由此线程来控制 ManualResetEvent,其它到这里来的线程请等待
                    // 为求简单易懂,本例实际上只有主线程会在这里循环运行
                    Thread.Sleep(500);
                    _connectDone.Reset();
                    
                    // 开始接受客户端传入的连接
                    _listener.BeginAccept(new AsyncCallback(OnClientConnect), null);
                    
                    // 阻止当前线程,直到当前 ManualResetEvent 调用 Set 发出继续信号
                    _connectDone.WaitOne();
                }
            }
            catch (SocketException ex)
            {
                
            }
            
        }

等待连接: private void OnClientConnect(IAsyncResult async)
        {
            // 当前 ManualResetEvent 调用 Set 以发出继续信号,从而允许继续执行一个或多个等待线程
            _connectDone.Set();
            ClientSocketPacket client = new ClientSocketPacket();
            // 完成接受客户端传入的连接的这个异步操作,并返回客户端连入的 socket
            client.Socket = _listener.EndAccept(async);

            // 将客户端连入的 Socket 放进客户端 Socket 列表
            _clientList.Add(client);
            _syncContext.Post(ResultCallback, client.Socket.RemoteEndPoint);
            try
            {
                // 开始接收客户端传入的数据
                client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, SocketFlags.None, new AsyncCallback(OnDataReceived), client);
            }
            catch (SocketException ex)
            {
                // 处理异常
                HandleException(client, ex);
            }
            //_listener.BeginAccept(new AsyncCallback(OnClientConnect), null);
        }


接收数据: private void OnDataReceived(IAsyncResult async)
        {
            ClientSocketPacket client = async.AsyncState as ClientSocketPacket;
            int count = 0;
            try
            {
                // 完成接收数据的这个异步操作,并返回接收的字节数
                if (client.Socket.Connected)
                    count = client.Socket.EndReceive(async);
            }
            catch (SocketException ex)
            {
                //MessageBox.Show(ex.Message.ToString());
                HandleException(client, ex);
                return;
            }
            // 把接收到的数据添加进收到的字节集合内
            // 本例采用UTF8编码,中文占用3字节,英文占用1字节,缓冲区为32字节
            // 所以如果直接把当前缓冲区转成字符串的话可能会出现乱码,所以要等接收完用户发送的全部信息后再转成字符串
            foreach (byte b in client.Buffer.Take(count))
            {
                if (b == 0) continue; // 如果是空字节则不做处理

                client.ReceivedByte.Add(b);
            }

            // 如果该 Socket 在网络缓冲区中没有排队的数据 并且 接收到的数据中有自定义的结束符时
            if (client.Socket.Connected && client.Socket.Available == 0)//&& receivedString.Contains(_endMarker)
            {

                #region 发送信息
                try
                {
                    string jsonString = Encoding.UTF8.GetString(client.ReceivedByte.ToArray());
                    ChatMessage msg = JsonConvert.DeserializeObject<ChatMessage>(jsonString);
                    if (string.IsNullOrEmpty(msg.SenderIPAndPort))
                    {
                        msg.SenderIPAndPort = client.Socket.RemoteEndPoint.ToString();//得到发送者的IP和端口号
                    }
                    msg.Sendtime = DateTime.Now;
                    SendM = msg;
                    //发送信息
                    client.ReceivedByte.Clear();//清空以准备下次接收
                    SendMsg(msg);
                    Thread.Sleep(100);

                }
                catch (Exception ex)
                {
                    //MessageBox.Show("aaa");
                }
                finally
                {


                }
                #endregion
            }

            try
            {
                // 继续开始接收客户端传入的数据
                if (client.Socket.Connected)
                    client.Socket.BeginReceive(client.Buffer, 0, client.Buffer.Length, 0, new AsyncCallback(OnDataReceived), client);
            }
            catch (SocketException ex)
            {
                HandleException(client, ex);
            }
        } --------------------编程问答-------------------- 死循环没有退出条件,长时间占用了CPU --------------------编程问答-------------------- while (true)
这个循环里头你要加一个Thread.Sleep(时间),不然程序直接堵死在这里边,当然CPU就100% --------------------编程问答-------------------- 用了异步回调,就不要用while (true){} --------------------编程问答-------------------- 这是不可能的
就看你怎么用了
一般连接数也是有上限的
不是说你多线程就是线程越多就越好
根据实际情况 做不同的操作
你可以做IOCP完成端口 提升性能 --------------------编程问答--------------------
引用 2 楼 zhantianyou 的回复:
while (true)
这个循环里头你要加一个Thread.Sleep(时间),不然程序直接堵死在这里边,当然CPU就100%



 while (true)
  {
  // 重置 ManualResetEvent,由此线程来控制 ManualResetEvent,其它到这里来的线程请等待
  // 为求简单易懂,本例实际上只有主线程会在这里循环运行
  Thread.Sleep(500);
  _connectDone.Reset();
    
  // 开始接受客户端传入的连接
  _listener.BeginAccept(new AsyncCallback(OnClientConnect), null);
    
  // 阻止当前线程,直到当前 ManualResetEvent 调用 Set 发出继续信号
  _connectDone.WaitOne();
  }
  }
  catch (SocketException ex)
  {
    
  }
已经加了啊…… --------------------编程问答--------------------
引用 3 楼 sunny906 的回复:
用了异步回调,就不要用while (true){}


这个地方我试过用异步,也是会出现cpu 90%多的情况 --------------------编程问答-------------------- 谢谢大家的回答,我用一个性能软件监测了一下,发现是我的接收数据函数private void OnDataReceived(IAsyncResult async)用一会之后就占用之量的CPU,但是我没有找到解决办法,请各位高手帮我看一下,或者加我的QQ,一起解决一下,万分感谢各位大侠……
--------------------编程问答-------------------- 多线程也看情况而定,不用的就sleep掉,不要浪费资源 --------------------编程问答--------------------
引用 8 楼 chenyingshu880603 的回复:
多线程也看情况而定,不用的就sleep掉,不要浪费资源


我这里面只有一个开了一个啊? --------------------编程问答-------------------- 看看客户端的构造函数中有什么while循环之类的一直在占用。 --------------------编程问答--------------------
引用 10 楼 chenyingshu880603 的回复:
看看客户端的构造函数中有什么while循环之类的一直在占用。

客户端发送的代码如下:没有循环,谢谢了
void Send(ChatMessage msg)
        {
            try
            {
                string _msgJsonString = JsonConvert.SerializeObject(msg);
                byte[] arrMsg = Encoding.UTF8.GetBytes(_msgJsonString);
                if (AppGlobal.Instance.SocketMain.Connected)
                {
                    // 设置需要发送的数据的缓冲区
                    AppGlobal.Instance.SocketMainArgs.BufferList =
                        new List<ArraySegment<byte>>() 
                    { 
                        new ArraySegment<byte>(arrMsg)// + _endMarker
                    };

                    // 异步地向服务端 Socket 发送消息
                    AppGlobal.Instance.SocketMain.SendAsync(AppGlobal.Instance.SocketMainArgs);
                    Thread.Sleep(100);
                }
                else
                {
                }
            }
            catch (Exception ex)
            {
                //OutPut(ex.Message.ToString());
            }
        } --------------------编程问答--------------------
引用 4 楼 fengyarongaa 的回复:
这是不可能的
就看你怎么用了
一般连接数也是有上限的
不是说你多线程就是线程越多就越好
根据实际情况 做不同的操作
你可以做IOCP完成端口 提升性能


这一块我不是很懂,请你详细指点下,谢谢了 --------------------编程问答--------------------
引用 1 楼 sudianbo 的回复:
死循环没有退出条件,长时间占用了CPU


你说的死循环是?麻烦你详细指点下,谢谢了
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,