我现在在做一个用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.异步问题:现在是采用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每秒都往服务器发送一次数据,采用哪种方法更好些?谢谢!
解决方案 »
- winform如何实现用户控件之间的属性修改。
- VS2005中ASP:TableCell里面的内容置顶
- 修改命名空间后出现的问题!
- 难道这些问题真的把所有人都难住了。。。?(我删贴,重贴好几次了。。。)
- 如何优化以下代码?请高手们教路
- 阻塞模式Socket 怎么也会出现: 无法立即完成一个非阻挡性套接字操作(WSAEWOULDBLOCK 10035) 错误?
- 能不能给我一个类似于qq或msn的发送文件的例子
- 求救~~~~~~~!!!谢谢(comboBox控件邦定数据时怎样获取的控件中的内容)
- 请教C#高手一道问题
- 请问高手:.net环境中怎样弹出一个messgae对话框!
- c# 怎么样使用多线程采集网页内容
- C#求助 大神,高手进.......
socketThread.Start(newSocket)
这里的newSocket是个什么东西?看你的代码它都不是准确的Accept结果,都不知道哪里蹦出来的全局变量,这能不乱、不冲突吗?一个异步的服务程序,根本没有什么while,也没有什么new Thread这样的代码。
listener 变量,我代码粘贴的有问题。
这个程序是两套程序,一个是用异步写的(现在的版本),一个使用多线程写的(以前的版本)。
“线程抢占资源” 我遇到的问题时这样的:比如我有10个客户端在发送数据,我这边开了10个线程都调用一个方法用socket监听,一段时间内,有7个线程执行,另外3个线程没有执行,我就认为7个线程把资源全抢走了,另外3个线程没抢到资源。
“线程同步问题” 多线程执行的方法内有一个接受数据的字节数组需要操作,多个线程去执行方法操作那个字节数组的时候就会出现同步问题,上一个线程把字节数组修改了但没有走完方法,下一个线程再去操作字节数组,那个数组值就不对了。
“死锁问题”我想解决同步问题,就想到了加锁,但加锁后就出现死锁。这是我写的第一个多线程程序,望高手能指点,诚心求教!谢谢!
你的while(true)是死循环
你可以换种判断方式啊
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);
}
/// <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;
}