socket连接多个服务器

问题描述

现在有一个项目是这种业务关系:一个pc需要以socket方式连接到至少10个服务端,然后服务端会不定时发送数据回来,pc端就将这些数据保存到数据库,用户就以wpf或者winform方式查看。受socket方式现在,需要单开线程进行查询有没有数据收到,从而进行处理,我试了几种方式,但结果都使电脑卡得连歌都不能正常播放。1.直接给每个socket连接开一个线程,这样就至少有10个线程,反正运行起来机会不能动2.以threadpool方式,并没有感觉到效果3.以select模型实现,效果倒是有,但是不大以上所有方式在控制台程序中还是不错,一转到winform就不行了。在这里向各位大神请教一下还有没有其他方式解决,什么方案都可以提。我这里想了一个改变架构的方式,编写控制台程序在一台服务器上(不懂服务器),专门负责解析数据,pc就只是从服务器调去数据,这样应该能最大解决pc性能问题,但是这样需要调动的资源就多了不知还有没有其他方法????

解决方案

解决方案二:
如果你非要用多线程,多线程里要加sleep,不要无限死循环其实你完全可以用异步方式编程,BeginReceive,有数据来了就会调用回调函数了不要开10个线程死等
解决方案三:
引用1楼Z65443344的回复:

如果你非要用多线程,多线程里要加sleep,不要无限死循环其实你完全可以用异步方式编程,BeginReceive,有数据来了就会调用回调函数了不要开10个线程死等

谢谢!!!找时间试一下不知道beginreceive的内部机制,就怕和select模型一样,将那些socket加入select模型只需要一个线程就能解决,但是最终结果却很失望。另外sleep是当头一棒,把这个给忘了,这个项目实时性要求不高,20s一次应该都没问题,还可以把缓存搞大点
解决方案四:
异步方式编程的机制就是基于windows消息循环,线程池动态执行,回调机制它可能会动态的开个线程去执行,也可能根本就是用当前线程去执行的(如果当前线程很空闲的话),总之你控制不了也不需要关心它到底被哪个线程去执行了,执行完就会调用回调函数好让你执行后续的代码你可以在BeginReceive之后,回调函数里,接收到数据了,然后存数据库,然后继续BeginReceive等待下一次的数据到来
解决方案五:
你需要的仅仅是10个tcpclient而已..
解决方案六:
写过连接很多的代码可能你没用不过你可以参考下.foreach(variteminRunData){varsocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);socket.Connect("",9999);var注册信息="5A-"+item.Key+"-E6-A5";socket.Send(注册信息.ToByte校验完成());System.Threading.Thread.Sleep(100);socket.BeginReceive(buffer,0,buffer.Length,SocketFlags.None,newAsyncCallback(ReceiveMessage),socket);Console.WriteLine("建立"+item.Key+"连接");}staticvoidReceiveMessage(IAsyncResultar){varsocket=ar.AsyncStateasSocket;try{varlength=socket.EndReceive(ar);byte[]reallData=newbyte[length];Array.Copy(buffer,reallData,length);doWork(newobjectState(){s=socket,data=reallData});}catch(Exception){}finally{socket.BeginReceive(buffer,0,buffer.Length,SocketFlags.None,newAsyncCallback(ReceiveMessage),socket);}}staticvoiddoWork(objecto){varrs=oasobjectState;byte[]data=rs.data;Socketar=rs.s;varcmd=data.ToHexString();}

都是客户端有数据自己判断是谁发送的就行了.
解决方案七:
最终也就是dict<string,int>serverserver.forsocket.con(key,value)socket.BeginReceive(xx,xx,xx,xx,newcallback(xxoo).null)voidxxoo(reslt){//所有服务端的数据都在这个方法里..通过socketserver的IP来判断是那个服务器}

简单的写下不是很麻烦把我上面的整理下就可以了.而且不涉及到什么"多线程"当然这异步的东西你要在UI上面显示还是得做点别的
解决方案八:
分明自己是服务器,却楞说成客户端。如果你是客户端,为何不能主动访问服务器?同步监听应采用select模型,不需要sleep以免误事(加入你刚挂起,数据就来了呢?)select本身就会挂起循环,直到通讯状态发生变化也可使用异步方式,不了解细节的话,有点不敢用绝对不要用demo方式,那只是帮助你理解通讯的过程。毫无实用价值
解决方案九:
引用7楼xuzuning的回复:

分明自己是服务器,却楞说成客户端。如果你是客户端,为何不能主动访问服务器?同步监听应采用select模型,不需要sleep以免误事(加入你刚挂起,数据就来了呢?)select本身就会挂起循环,直到通讯状态发生变化也可使用异步方式,不了解细节的话,有点不敢用绝对不要用demo方式,那只是帮助你理解通讯的过程。毫无实用价值

他所有的服务端都是推送的方式,所以他这个确实是客户端,而不是服务器
解决方案十:
Dictionary<string,int>server=newDictionary<string,int>();server.Add("192.168.1.1",2222);server.Add("192.168.1.2",2222);server.Add("192.168.1.3",2222);server.Add("192.168.1.4",2222);server.ToList().AsParallel().ForAll(item=>{varclient=newSystem.Net.Sockets.TcpClient();client.Connect(item.Key,item.Value);client.Client.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None,newAsyncCallback(ReceiveMessage),client);});voidReceiveMessage(IAsyncResultar){varsocket=ar.AsyncStateasSocket;try{varlength=socket.EndReceive(ar);byte[]reallData=newbyte[length];Array.Copy(buffer,reallData,length);ThreadPool.QueueUserWorkItem(newWaitCallback((state)=>{doWork(newobjectState(){s=socket,data=reallData});}));}catch(Exception){}finally{socket.BeginReceive(buffer,0,buffer.Length,SocketFlags.None,newAsyncCallback(ReceiveMessage),socket);}}staticvoiddoWork(objecto){varrs=oasobjectState;byte[]data=rs.data;Socketar=rs.s;}

至于你后面提到的解决方案如果你需要看历史数据那么把数据存放起来一定是一个不错的选择.如果实时性的话真的不需要服务器了你可以本地直接连接10台服务器拿数据没有必要自己做一个服务器然后在转发到本地...就相当于你的软件作为客户端连接服务器但是实际上服务器作为10个tcp服务器的客户端又去连接他们
解决方案十一:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Net.Sockets;usingSystem.Threading;namespaceConsoleApplication2{classProgram{staticbyte[]buffer=newbyte[1024];staticvoidMain(string[]args){Dictionary<string,int>server=newDictionary<string,int>();server.Add("192.168.1.119",9949);server.Add("192.168.1.105",9949);server.ToList().AsParallel().ForAll(item=>{Console.WriteLine("con");varclient=newTcpClient();client.Connect(item.Key,item.Value);client.Client.BeginReceive(buffer,0,buffer.Length,System.Net.Sockets.SocketFlags.None,newAsyncCallback(ReceiveMessage),client);});Console.ReadLine();}staticvoidReceiveMessage(IAsyncResultar){varsocket=ar.AsyncStateasTcpClient;try{varlength=socket.Client.EndReceive(ar);byte[]reallData=newbyte[length];Array.Copy(buffer,reallData,length);ThreadPool.QueueUserWorkItem(newWaitCallback((state)=>{doWork(newobjectState(){s=socket,data=reallData});}));}catch(Exceptionex){Console.WriteLine(ex.Message);}finally{socket.Client.BeginReceive(buffer,0,buffer.Length,SocketFlags.None,newAsyncCallback(ReceiveMessage),socket);}}staticvoiddoWork(objecto){varrs=oasobjectState;vara=string.Join("-",rs.data.Select(d=>d.ToString("X2")).ToArray());Console.WriteLine(a);}}}publicclassobjectState{publicTcpClients{get;set;}publicbyte[]data{get;set;}}

解决方案十二:
上面的代码,我用了2个"服务器"做了测试通过了你想要的结果..1`成功连接服务器并且在2个服务器上分别看到1条来自同一个客户端的长连接..2`使用服务器分别给这2个长连接发送数据客户端都可以收到并且执行了doWork方法.到此你的业务走完成了.但是你的需求不仅如此..因为你要通过不同服务器发送来的数据做不同的操作..所以objectState.s字段就可以拿到服务器的信息(ip)就可以做你想要的了..
解决方案十三:
引用11楼diaodiaop的回复:

上面的代码,我用了2个"服务器"做了测试通过了你想要的结果..1`成功连接服务器并且在2个服务器上分别看到1条来自同一个客户端的长连接..2`使用服务器分别给这2个长连接发送数据客户端都可以收到并且执行了doWork方法.到此你的业务走完成了.但是你的需求不仅如此..因为你要通过不同服务器发送来的数据做不同的操作..所以objectState.s字段就可以拿到服务器的信息(ip)就可以做你想要的了..

你的解决方案效果挺好,很明显,我还加大到20个socket都没什么影响。另外发现一个问题起始那一两次数据接收是乱序的,后面的数据都按创建连接对象的反向顺序调用回调的
解决方案十四:
引用7楼xuzuning的回复:

分明自己是服务器,却楞说成客户端。如果你是客户端,为何不能主动访问服务器?同步监听应采用select模型,不需要sleep以免误事(加入你刚挂起,数据就来了呢?)select本身就会挂起循环,直到通讯状态发生变化也可使用异步方式,不了解细节的话,有点不敢用绝对不要用demo方式,那只是帮助你理解通讯的过程。毫无实用价值

谢谢提醒,但是我这边确实是客户端,只是这个概念在这里正好容易让人混淆。我这个服务器并不是指那种大型服务器,而只是一个带socketservice的网络设备
解决方案十五:
顶一下,我这边正好也要做这样的项目,学习了

时间: 2024-09-16 09:58:39

socket连接多个服务器的相关文章

安卓源码-安卓代码无法socket连接个人笔记本服务器~一直没能解决这个问题,求帮助

问题描述 安卓代码无法socket连接个人笔记本服务器~一直没能解决这个问题,求帮助 服务器代码: import java.awt.FlowLayout; import java.awt.Frame; import java.awt.TextArea; import java.awt.TextField; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedR

服务器-笔记本没办法接收到android客户端的socket连接

问题描述 笔记本没办法接收到android客户端的socket连接 服务器是java写的,在笔记本上面运行.用java的客户端倒是可以连接,但是android写的就不行了.双方程序都是没问题的,台式机测试过. 试过用wifi连接,用网线连接都不行.还有一个问题就是在网上查的ip跟网络连接上面的ip完全不一样 解决方案 啥叫"在网上查的ip跟网络连接上面的ip完全不一样"?android的socket就是java里面滴.据你描述,问题可能出在ip上吧,另外端口也注意. 解决方案二: 你的

c++用socket连接,如何把服务器的本地文件夹目录传给客户端

问题描述 c++用socket连接,如何把服务器的本地文件夹目录传给客户端 c++用socket连接,如何把服务器的本地文件夹目录传给客户端,并且提供下载,求助 解决方案 1.定义客户端和服务器间通信协议 如针对你的应用: (1)客户向服务器请求目录结构: (2)服务器向客户端返回目录结构: (3)客户端向服务器请求下载指定目录或文件. 2.服务器通过遍历等方式获得目录结构 3.编程实现:定义消息类型.数据结构.数据收发.... 解决方案二: 文件目录很容易,可以system("dir>1

线程-使用Java socket让客户端与服务器建立连接后,服务器如何判断来自客户端的各类请求

问题描述 使用Java socket让客户端与服务器建立连接后,服务器如何判断来自客户端的各类请求 初学java,目前写了一个服务端和一个客户端.大致了解了如何socket通信是如何操作的,并且初步实现了客户端和服务端的通信.也仅仅是是接受和返回简单的字符串.部分代码如下 public void run(){ try{ serverSocket=new ServerSocket(SERVER_PORT_ONE); System.out.println("serversocket已创建"

服务器-C#Socket连接,第一次要很久

问题描述 C#Socket连接,第一次要很久 各位,我写了个 Socket 程序,服务端总是开启着,客户端偶尔连接.偶尔断开.现在如果客户端断开很久后再去连服务器,第一次要很久才能连接成功.大家有没有碰到这种情况? 麻烦各位大侠多指点. 解决方案 我也遇到了这样的问题,该如何解决

C/S架构,SOCKET连接,服务器和客户端之间通信为什么会丢包?

问题描述 C/S架构,SOCKET连接,服务器和客户端之间通信为什么会丢包? C/S架构,SOCKET连接,服务器和客户端之间通信为什么会丢包 解决方案 iOS用GcdAsyncsocket通信一个8000多字节的包只能收到一千多字节,这是什么原因

通信-android 客户端socket连接服务器,socket何时close

问题描述 android 客户端socket连接服务器,socket何时close 假设socket连接好了,现在客户端向服务器发送完了数据,这个时候需要关闭socket吗?如果关闭后,某个时候又需要发送其他数据,再建立连接? 还是说建立通信协议,一次socket连接后一直保持通信状态,根据通信协议对不同的数据进行不同的处理,然后等客户端程序退出时再关闭socket. 解决方案 Android客户端通过Socket连接服务器Android客户端与java服务器端的Socket连接Socket服务

http服务器-关于使用socket连接http代理服务器的问题

问题描述 关于使用socket连接http代理服务器的问题 使用代理服务器访问网页的时候, 创建Sokcet Connect服务器之后应该以什么格式提交包? 直接在要提交的包里加"Proxy-Authorization"就可以吗? 我测试的时候直接把 "GET http://www.baidu.com HTTP/1.1 Host: www.baidu.com Proxy-Connection: Keep-Alive Proxy-Authorization: Basic &qu

与tomcat服务器建立socket连接

问题描述 环境: tomcat+ssh2(Struts2,Spirng,Hibernate)现在希望客服端与tomcat服务器(或struts2的Action,servlet)建立socket连接客服端是MFC写的程序不知道这样行不行,或者大家有什么更好的方式?我是小菜鸟,请大家给俺出出主意! 问题补充:二楼的大侠可否说的具体一点我的要求就是MFC写的程序能和tomcat+struts2+spirng+hibernate搭建的服务器交换数据如果不能和action,servlet通信的话,有什么替