socket编程,多端口 大家好,我现在有个项目,是socket通讯的。客户端已做好,是别人做的。每个客户端用到一个独立的端口,最多是999个,请问我上位机得针对这999个独立端口开启999个服务进行侦听吗?那是不是会创建太多的线程? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 当然不用,因为服务器的端口就一个,就监听这一个端口就行了,就用一个或几个线程去监听端口的消息然后把收到的连接存放到一个表中,比如hashtable根据端口收到的消息再取到对应的连接进行处理 纠正下楼主的概念,“上位机”个人认为应该是相对于嵌入式终端的“下位机”而言的吧。这里应该说成“客户端”和“服务器”吧?你所说的每个客户端用到一个独立端口,是指每个客户端程序都访问你服务器的一个特定端口呢?还是指的每个客户端都用自己的某一个端口访问你服务器上的相同的一个端口?比如每个客户端都访问服务器的8888端口?如果是前一种情况,你就得为每一个客户端要访问的每个端口都建立一个线程,然后侦听客户端的连接。如果是后一种情况(我估计99%是这种情况),你只需启动一个线程,然后侦听客户端需要连接到的你的服务器的这个端口,每当收到一个连接的时候,就启动一个线程,把这个连接的客户端Socket(Accept会返回一个客户端socket对象)作为线程目标函数的参数传到线程的目标函数里去,然后再在这个函数里处理跟客户端之间的收发数据即可。 listen那么多不是cpu线程,不会死机的。不行你测试一下看看。 beginaccept和acceptasync都不是使用处理器线程的,除非你硬性开1000个处理器线程,那就不行了。 如果你实在没办法让他们都来连接你的服务器上的同一端口的话,那么只有祈祷了……请参考如下文章:讨论:一个进程(Process)最多可以生成多少个线程(Thread) 客户端的内容是早就做好了,我们现在是配合他们升级服务器端软件,原来用的vb做的c/s的。现在我想改为b/s的,但通讯这块还得借就以前的模式,他们当时客户端上传时没有客户端的标志,这样若服务器使用同一端口跟他们所有的连接时,给客户端发送信息就不知该如何发,才能发给指定的那个客户端了。 我的客户端中不是固定ip,用的手机卡,走的gprs,ip是动态的,就是停一次电后ip会变的。 那你就放心监听1000个端口吧,不会产生1000个cpu线程,不用担心。 为了让你更加放心,我测试了一下1000个socket监听1000个端口并beginaccept,结果cpu占用0,内存4兆,给你看一下数据,嘿嘿。原因我在前面已经解释过,这些是io线程,不是处理器线程。 太感谢lizhibin11了,这下我就放心了,非常感谢! 提醒一下,一定不要用thread,而是用socket异步编程,例如beginaccept、beginreceive、beginsend或者socketasynceventargs,这些都是完成端口的,创建的是io线程。 哦,我正在考虑用thread怎么实现开辟999个呢,你说的异步这个我还得看一下,以前做时用的是thread,所以也考虑用这个呢。 lizhibin11你好,你是怎么创建的那个测试1000个端口接收的程序的,能发给我看看吗?[email protected] using System;using System.Net;using System.Net.Sockets;namespace ConsoleApplication7{ class Program { static void Main(string[] args) { for (int i = 0; i < 1000; i++) { Socket sk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); sk.Bind(new IPEndPoint(IPAddress.Parse( "192.168.1.101"), 10000 + i)); sk.Listen(1); sk.BeginAccept(acceptCallBack, sk); } Console.WriteLine("ok"); Console.ReadLine(); } static void acceptCallBack(IAsyncResult result) { Socket sk = (Socket)result.AsyncState; sk = sk.EndAccept(result); byte[] b = new byte[1024]; sk.BeginReceive(b, 0, b.Length, SocketFlags.None, ReceiveCallBack, sk); } static void ReceiveCallBack(IAsyncResult result) { Socket sk = (Socket)result.AsyncState; int len = sk.EndReceive(result); //........................ } }}测试程序,只是雏形。正式应用需要有全局集合保存socket以便调用它发送东西。 如果你跟下位机的通信协议里包含了手机号的话,最好用手机号做区分,这样也可以避免占用1000个端口的问题。另外提醒你一下。如果服务器不需要用DNS服务的话,把服务器的DNS服务停掉,不然的话,容易造成端口被占用完的问题,导致无法接收数据。我曾经碰到过。 这个是轮询啊,而且sk.BeginAccept(acceptCallBack, sk);需要放到线程的while死循环里用for语句执行1000个socket的轮询,异步接收数据。轮询到了还要用个queue去保存当前通讯的ip地址,用来处理发送逻辑。 如果是用.net做,就用异步通讯轻松实现,如果是用vc做,就用完成端口也可以轻松实现,二者实质一样。 怎么需要那么多线程 谁还用同步???去下个北风之神SOCKET 框架看下 就知道了 还是服务器同一端口监听比较现实应该有mac地址可作识别,如果是用udp通讯,每次通讯前,可以先广播一个命令(一般应该有这样的命令让下位机返回自己信息),让所有客户端给服务器返回信息(最好有mac这样的标识信息),这样你就能动态记录它们各自的标识信息+动态ip+端口号了 webbrowser右键菜单 关于数据同步的一些问题 Dev GridControl中Keypress里面的上下箭头 关于SqlDependency问题? 如何实现这种功能 ■■■■■■■■■■outlook文件夹默认放在我的文档里,占用空间怎么办 带数字的字符串排序问题?? 100高分紧急求救.net高手:C# 提取HTML源码元素坐标/属性(width,height) 使用HttpWebRequest如何訪問本機localhost的url 初学C#问个问题 WebService编程 [WPF]使用StreamSource显示图片后,应该在什么时候Close
你所说的每个客户端用到一个独立端口,是指每个客户端程序都访问你服务器的一个特定端口呢?还是指的每个客户端都用自己的某一个端口访问你服务器上的相同的一个端口?比如每个客户端都访问服务器的8888端口?
如果是前一种情况,你就得为每一个客户端要访问的每个端口都建立一个线程,然后侦听客户端的连接。
如果是后一种情况(我估计99%是这种情况),你只需启动一个线程,然后侦听客户端需要连接到的你的服务器的这个端口,每当收到一个连接的时候,就启动一个线程,把这个连接的客户端Socket(Accept会返回一个客户端socket对象)作为线程目标函数的参数传到线程的目标函数里去,然后再在这个函数里处理跟客户端之间的收发数据即可。
请参考如下文章:讨论:一个进程(Process)最多可以生成多少个线程(Thread)
太感谢lizhibin11了,这下我就放心了,非常感谢!
using System;
using System.Net;
using System.Net.Sockets;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 1000; i++)
{
Socket sk = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
sk.Bind(new IPEndPoint(IPAddress.Parse( "192.168.1.101"), 10000 + i));
sk.Listen(1);
sk.BeginAccept(acceptCallBack, sk);
}
Console.WriteLine("ok");
Console.ReadLine();
}
static void acceptCallBack(IAsyncResult result)
{
Socket sk = (Socket)result.AsyncState;
sk = sk.EndAccept(result);
byte[] b = new byte[1024];
sk.BeginReceive(b, 0, b.Length, SocketFlags.None, ReceiveCallBack, sk);
}
static void ReceiveCallBack(IAsyncResult result)
{
Socket sk = (Socket)result.AsyncState;
int len = sk.EndReceive(result);
//........................
}
}
}测试程序,只是雏形。正式应用需要有全局集合保存socket以便调用它发送东西。
另外提醒你一下。如果服务器不需要用DNS服务的话,把服务器的DNS服务停掉,不然的话,容易造成端口被占用完的问题,导致无法接收数据。我曾经碰到过。
需要放到线程的while死循环里用for语句执行1000个socket的轮询,异步接收数据。
轮询到了还要用个queue去保存当前通讯的ip地址,用来处理发送逻辑。
应该有mac地址可作识别,如果是用udp通讯,每次通讯前,可以先广播一个命令(一般应该有这样的命令让下位机返回自己信息),让所有客户端给服务器返回信息(最好有mac这样的标识信息),这样你就能动态记录它们各自的标识信息+动态ip+端口号了