我现在在做一个用Socket通过TCP/IP采集DTU数据的程序,DTU相当于客户端,目前有5个左右,每个DTU每秒钟都会向服务器发送一次数据,我要采集这些数据。
现在虽然开发出来了,但我觉得我在采集的时候处理的不是很好,想请各位帮我分析,指点一下。1.异步问题:现在是采用Socket异步的方式进行采集数据的,遇到的问题是线程同步的问题:多个DTU同时向我的服务器发送数据,DTU发送数据的频率是一样的,一段时间内,有的DTU能收到好多次,但有的DTU过了很久才能收到一两次。我必须保证DTU发送数据后,两分钟内能收到数据,否则DTU就会死掉了。我想到了用线程同步,我在异步接收数据的时候加了锁,希望程序能按一定顺序读取DTU的数据,虽然貌似实现了,10秒内服务器都能收到每个DTU发来的数据,但还是对这个原理不太理解,我查了一些资料,也没有说这个锁能够维护线程的执行顺序,也不知道自己做得对不对主要代码如下:        //异步接收数据
        private void readCallback(IAsyncResult ar)
        {
            lock (lockObj)
            {
                Monitor.Pulse(lockObj);//释放锁
                Socket handler = null;
                handler = (Socket)ar.AsyncState;
                int  bytesRead = handler.EndReceive(ar);
                if (bytesRead > 0)
                {
                    //必要解析数据,回心跳包操作 略
                 }
                //递归接收数据
                handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
              new AsyncCallback(readCallback), state);
              Monitor.Wait(lockObj, 1000);//关闭锁            }
      } 
2.多线程问题:我以前是用多线程来实现的,但也是遇到线程抢占资源,同步,死锁问题就写不下去了改用异步处理了,主要代码如下:
//检测DTU上线的方法
        private void AcceptData()
{
while(true)
{
       Socket listener = socket.Accept();
  Thread socketThread = new Thread(new ParameterizedThreadStart(ThreadReceiveData));//每上线一个DTU就开启一个线程监听数据
                    socketThread.Start(newSocket);
}
}//接受DTU数据的方法
        private void ThreadReceiveData(Object socketObj)
{
                Socket threadSocket = socketObj as Socket;
                while (true)
                {
                    lock (this)//这个地方很纠结,不加锁的话,线程之间就会抢占资源,导致某些线程长时间接收不到
数据导致死掉
                    {
                       receiveDatas = new byte[1024];
                    threadSocket.Receive(receiveDatas);
                    //必要解析数据,回心跳操作 略
                    }
                }
}
还有个问题,就是多线程和异步,哪个性能更高一些,像我这种情况,每个DTU每秒都往服务器发送一次数据,采用哪种方法更好些?谢谢!

解决方案 »

  1.   

    加锁你好搞什么异步、多线程干什么呢?不会编写多线程程序,也别用锁来欺骗自己啊。“线程抢占资源,同步,死锁问题”是什么问题呢?你弄两个while循环这个问题也就算了。问题是
      socketThread.Start(newSocket)
    这里的newSocket是个什么东西?看你的代码它都不是准确的Accept结果,都不知道哪里蹦出来的全局变量,这能不乱、不冲突吗?一个异步的服务程序,根本没有什么while,也没有什么new Thread这样的代码。
      

  2.   

    newSocket 就是  Socket listener = socket.Accept();
    listener 变量,我代码粘贴的有问题。
    这个程序是两套程序,一个是用异步写的(现在的版本),一个使用多线程写的(以前的版本)。
      

  3.   


    “线程抢占资源” 我遇到的问题时这样的:比如我有10个客户端在发送数据,我这边开了10个线程都调用一个方法用socket监听,一段时间内,有7个线程执行,另外3个线程没有执行,我就认为7个线程把资源全抢走了,另外3个线程没抢到资源。
    “线程同步问题”  多线程执行的方法内有一个接受数据的字节数组需要操作,多个线程去执行方法操作那个字节数组的时候就会出现同步问题,上一个线程把字节数组修改了但没有走完方法,下一个线程再去操作字节数组,那个数组值就不对了。
    “死锁问题”我想解决同步问题,就想到了加锁,但加锁后就出现死锁。这是我写的第一个多线程程序,望高手能指点,诚心求教!谢谢!
      

  4.   

    LZ刚看你代码
    你的while(true)是死循环
    你可以换种判断方式啊
      

  5.   

    while(true)里面有个锁,这次锁执行完了,继续执行这个锁,一直锁!异步里面几个回调函数都没充分利用!既然写异步干嘛还用循环捏!
      

  6.   

    这是两个版本的程序:
    1.异步问题:这是一个版本的用异步做的程序
    2.多线程问题: 这是另外一个版本用多线程做的程序异步里面没有用循环,用的都是异步回调的方法。
    因为代码里涉及到一些业务操作,我怕都贴出来了,大家会看得比较累,就贴一些个人认为比较关键的地方
             /// <summary>
            /// 异步接受请求
            /// </summary>
            /// <param name="ar"></param>
            private void AcceptCallback(IAsyncResult ar)
            {
                       Socket listener = (Socket)ar.AsyncState;
                       Socket  newSocket = listener.EndAccept(ar);
                        newSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,    new AsyncCallback(readCallback), state);
            }
      

  7.   

    不好意思,最后一行贴的有问题应该是这样的
    /// <summary>
      /// 异步接受请求
      /// </summary>
      /// <param name="ar"></param>
      private void AcceptCallback(IAsyncResult ar)
      {
       StateObject state = new StateObject();
      Socket listener = (Socket)ar.AsyncState;
      Socket newSocket = listener.EndAccept(ar);
       state.workSocket = newSocket;
      newSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
        new AsyncCallback(readCallback), state);
       listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
     }        public class StateObject
            {
                // Client  socket.
                public Socket workSocket = null;
                // Size of receive buffer.
                public const int BufferSize = 1024;
                // Receive buffer.
                public byte[] buffer = new byte[BufferSize];
                //GPRSID
                public string gprsid = string.Empty;   
            }
      

  8.   

    http://blog.csdn.net/fengyarongaa/article/details/6631953