问题描述
上位机(主控室)与多个下位机通信(TCP/ip通信),接收多个下位机(大约100台)传过来的数据,每台下位机的数据量大约100k/s。两种接收方式:1.上位机开辟多线程,每个线程分别与每台下位机相连。下位机分别实时主动送数据,100个线程并行传输数据会不会有问题?2.上位机采用轮询方式,向某台下位机要数据,单线程即可解决,这样不会出现并行传输数据的问题,但是需要在每台下位机装配IP主节点存储下位机的数据,增加了成本。由于现在只实现了上位机与两台下位机连接,采用的方式1,目前对100台下位机连接时有疑惑和顾虑。请问上述数据接收处理方式是否合理?有没有更合理的接收方式?
解决方案
解决方案二:
引用楼主u010018424的回复:
1.上位机开辟多线程,每个线程分别与每台下位机相连。下位机分别实时主动送数据,100个线程并行传输数据会不会有问题?
服务器端通讯应该是异步并发的,就算是10万个下位机与上位机进行实时通讯,在某一个瞬间,你也不能说有100001个线程在那里死循环着。可能一个线程都不用,或者可能最多(瞬间)用20个线程,总之不能纠结那么多线程数。有些人完全是滥用线程去胡写代码,这可能跟msdn上某个具体通讯语句的特殊“范例”的误导有关,也可能是跟10几年前某些java书上的例子有关。比如说,.net中对属性的改变进行监听,实际上应该使用的编程模式是INotifyPropertyChanged接口。而有些人偏偏说“我用一个死循环执行的线程,不是仅能‘监控’变量值了吗?”。再比如说,当用将桌面上的窗口拖到桌面边缘时应该将窗口收缩起来,有的人就会滥用一个50毫秒的定时器不断轮询判断窗口是否在桌面边缘,而实际上应该使用的方式是捕获窗口被拖动的事件去判断.....基于滥用轮询、线程的方式编程,这从出发点就是错的。假设你只是1、2个线程滥用,也许你觉得没有什么。顶多就是电脑似乎卡了一点点,“还能忍受”。但是你需要迅速从2个线程过渡到“1万个线程”的情况,此时你不可能随手有20G内存、1000GHz主频的CPU,你还是得老老实实地使用“事件驱动”的异步编程思路。此时一个线程都不用,根本就跟线程数无关。100个下位机跟上位机实时连接,这不占用1个线程。你怎么反而能说要占用100个线程呢?可见你现在程序该立刻重写。
解决方案三:
电脑要干什么异步的事情,首先想到的是“注册好事件捕获机制”。你不用调用人家的方法,人家回回调你的。如果你的思路就是滥用“线程”,那就没救了。
解决方案四:
你不用调用人家的方法,人家回回调你的-->你不用调用人家的方法,人家会回调你的线程这个高大上的词儿让一些人疯狂。msdn上某个通讯语句的错误的阻塞式编程“范例”也助长了这种任性滥用线程的情况。实际上,如果只是在偶尔仅仅有1、2个连接且1分钟才需要连接一次的短连接的例子,才可能随便那样编程。
解决方案五:
用消息队列。下位机往上位机发数据,上位机用一个线程收数据,然后不做任何处理丢到消息队列中,上位机后台再开N个线程去处理消息队列中的任务。如果担心一个线程接收慢,多开几个也行,搞个线程池。上面的模型对付数百并发足够了,如果并发几千几万,可以参考完成端口模型。
解决方案六:
引用1楼sp1234的回复:
Quote: 引用楼主u010018424的回复:
1.上位机开辟多线程,每个线程分别与每台下位机相连。下位机分别实时主动送数据,100个线程并行传输数据会不会有问题?服务器端通讯应该是异步并发的,就算是10万个下位机与上位机进行实时通讯,在某一个瞬间,你也不能说有100001个线程在那里死循环着。可能一个线程都不用,或者可能最多(瞬间)用20个线程,总之不能纠结那么多线程数。有些人完全是滥用线程去胡写代码,这可能跟msdn上某个具体通讯语句的特殊“范例”的误导有关,也可能是跟10几年前某些java书上的例子有关。比如说,.net中对属性的改变进行监听,实际上应该使用的编程模式是INotifyPropertyChanged接口。而有些人偏偏说“我用一个死循环执行的线程,不是仅能‘监控’变量值了吗?”。再比如说,当用将桌面上的窗口拖到桌面边缘时应该将窗口收缩起来,有的人就会滥用一个50毫秒的定时器不断轮询判断窗口是否在桌面边缘,而实际上应该使用的方式是捕获窗口被拖动的事件去判断.....基于滥用轮询、线程的方式编程,这从出发点就是错的。假设你只是1、2个线程滥用,也许你觉得没有什么。顶多就是电脑似乎卡了一点点,“还能忍受”。但是你需要迅速从2个线程过渡到“1万个线程”的情况,此时你不可能随手有20G内存、1000GHz主频的CPU,你还是得老老实实地使用“事件驱动”的异步编程思路。此时一个线程都不用,根本就跟线程数无关。100个下位机跟上位机实时连接,这不占用1个线程。你怎么反而能说要占用100个线程呢?可见你现在程序该立刻重写。
谢谢哥哥的详细耐心的回答。其实开始用多线程编程就是图省事,保证数据独立、安全。拿方式1来说,说是下位机主动送,其实只有我主动去读,下位机才送过来数据。在每个线程中收到的数据,进行异步存储和显示(初始时用的委托事件,但是数据量大,处理不过来),然后再读下一次。开的线程会一直连续接收数据,不是短链接。
解决方案七:
引用4楼intraweb的回复:
用消息队列。下位机往上位机发数据,上位机用一个线程收数据,然后不做任何处理丢到消息队列中,上位机后台再开N个线程去处理消息队列中的任务。如果担心一个线程接收慢,多开几个也行,搞个线程池。上面的模型对付数百并发足够了,如果并发几千几万,可以参考完成端口模型。
谢谢,我去学习一下消息队列
解决方案八:
引用3楼sp1234的回复:
你不用调用人家的方法,人家回回调你的-->你不用调用人家的方法,人家会回调你的线程这个高大上的词儿让一些人疯狂。msdn上某个通讯语句的错误的阻塞式编程“范例”也助长了这种任性滥用线程的情况。实际上,如果只是在偶尔仅仅有1、2个连接且1分钟才需要连接一次的短连接的例子,才可能随便那样编程。
http://bbs.csdn.net/topics/391034226我的问题和连接里的问题差不多,都是长连接,不用开多线程吗?