当前位置:编程学习 > C#/ASP.NET >>

如何用SOCKET监听多个端口

我目前在一个项目中需要监听两个端口;我以前只用过SOCKET监听一个端口,所以我的想法很简单,就是新建两个线程,每个线程新建一个服务端,绑定一个端口,这样就可以监听两个端口了,代码如下 :

 private void button1_Click(object sender, EventArgs e)
        {
            socketOneThread = new Thread(new ThreadStart(StartService1));
            socketOneThread.Start();
            
            //加延时5s 
            Thread.Sleep(2000);
            
             socketTwoThread = new Thread(new ThreadStart(StartService2));
             socketTwoThread.Start();
            
      }

        public void StartService1() 
        {
            try 
            {
                //Create the listening socket
                this._mainSocketOne = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint ipLocal = new IPEndPoint(IPAddress.Parse("192.168.1.166"), 4001);

                //Bind to local IP Address
                this._mainSocketOne.Bind(ipLocal);

                //Start Listening
                this._mainSocketOne.Listen(10);                

                //Create the call back for any client connecting...
                this._mainSocketOne.BeginAccept(new AsyncCallback(OnClientConnectOne), null);
                //if (workerSocketOne.Connect)
                {
                    MessageBox.Show("CONNECTING OK!!!");
                }

               MessageBox.Show("_mainSocketOne.BeginAccept");
                
            }
            catch(SocketException se) 
            { 
                MessageBox.Show(se.ToString()+"server1");
            }
        }

        public void StartService2()
        {
            try
            {
                //Create the listening socket
                this._mainSocketTwo = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint ipLocal2 = new IPEndPoint(IPAddress.Parse("192.168.1.166"), 4002);

                //Bind to local IP Address
                this._mainSocketTwo.Bind(ipLocal2);

                //Start Listening
                this._mainSocketTwo.Listen(10);

                //Create the call back for any client connecting...
                this._mainSocketTwo.BeginAccept(new AsyncCallback(OnClientConnectTwo), null);
               // MessageBox.Show("_mainSocketTwo.BeginAccept");

            }
            catch (SocketException se)
            {
                MessageBox.Show(se.ToString() + "server2");
            }
        }


目前这样弄好像是可以,但我心里没有底,各位大虾,在一个程序里是不是可以新建多个服务端啊,你们监听多个端口的时候是怎么解决的,我想要一个简单又可靠的方法。谢谢啊,一定给分。 --------------------编程问答-------------------- 这个是可以的吧,可以监听多个端口的,不过假如多个端口传输量大的话,很容易假死状态。
比如,你在服务器上可以上网80端口,可以上QQ:8000端口,可以上3389端口,可以开启21端口,可以TELENT等 --------------------编程问答-------------------- 楼上的,你做过这样的程序没有啊,如果能找到做过这种程序的人核实一下就好了,从原理上来看,也应该是可以。 --------------------编程问答-------------------- 要是谁能够贴一些多端口监听的代码就更好了,因为毕竟这种情况也是经常要遇到的啊, --------------------编程问答-------------------- 还有一个问题,如何让通过线程中新建的SOCKET,发送一些指令出去啊。因为Accetp()中的SOCKET,都是通过线程新建的,那我如何使用这些用线程新建的SOCKET啊。 --------------------编程问答-------------------- 两个端口
是同一个业务服务还是不同的业务服务?
如果是不同的业务服务,可以分为多个进程处理
当然
底层通信类仍然可以使用同一个类

如果是同一个业务服务
确实可以开多个Socket然后绑定多个端口
但我认为没必要开多个端口




--------------------编程问答-------------------- 楼上的,我的两个端口分别接收不同设备发过来的数据。
如何分多个进程啊,我上面的程序代码就是分多线程写的啊,如果不开多个Socket然后绑定多个端口,那要怎么做呢,能给一点代码吗,或者说,我上面的代码如何改啊,在线等。 --------------------编程问答-------------------- 要是每个客户端数据量都很大,开辟多个端口,对每个具体的客户端设置制定的端口,在服务器些处理端口号的程序,使用线程通信。但如果是每个客户端数据量不是很大的话可以考虑设计通信协议,通过通信协议处理事物。 --------------------编程问答-------------------- 楼上说的我不是很明白啊,是不是当每个客户端数据量都很大的时候,开辟多个SOCKET服务端,每个服务端作为一个线程来监听指定的端口啊, --------------------编程问答-------------------- + $exception {"通常每个套接字地址(协议/网络地址/端口)只允许使用一次。"} System.Exception {System.Net.Sockets.SocketException}
--------------------编程问答-------------------- 不知如何解决 --------------------编程问答-------------------- 如何解决,我现在也在做这样的一个服务, --------------------编程问答-------------------- 我也遇到了同样的问题,顶贴,期待大牛回复 --------------------编程问答--------------------
引用 4 楼 lh1611 的回复:
还有一个问题,如何让通过线程中新建的SOCKET,发送一些指令出去啊。因为Accetp()中的SOCKET,都是通过线程新建的,那我如何使用这些用线程新建的SOCKET啊。

你有新的连接创建的Socket可以放入全局的集合里。到时候就去集合里找就行了。 --------------------编程问答-------------------- 楼主是如何解决的呢 ,我现在也遇到这个问题了 呜呜... --------------------编程问答-------------------- 绑定多个端口与一个端口感觉没有任何好处啊。 --------------------编程问答-------------------- 多个端口,完全没有问题啊,我就经常在项目上这么干。每个监听端口单独在一个线程中运行, 一般情况下 互不影响。 --------------------编程问答-------------------- 大侠 可不可以贴出来点代码,怎么样才能监听多个端口 --------------------编程问答-------------------- 多线程是可以的,但是如果情况是我不清楚事件发生在哪个端口,而需要对几乎所有的端口进行相应怎么做?

想来osi模型中更低的一层,所有的包都是由一个端口进来的,可以用事件的端口模型来侦听所有端口。

Index=WSAWaitForMultipleEvents(EventTotal,Event,FALSE,30,FALSE);
      switch (Index)
     {
        case WSA_WAIT_EVENT_0:
  {
          WSAEnumNetworkEvents(Socket[Index],Event[Index],&NetworkEvents);
          if (NetworkEvents.lNetworkEvents&FD_READ)
         {
             switch (Index)
            {
       case 0: //第0个端口
                case 1: //第一个端口
                  。。。。。
           }
    }                
  这样当每个端口有事件时程序会自动响应
但觉得还是比较麻烦 --------------------编程问答-------------------- 这个问题同样碰到了,求解啊 --------------------编程问答-------------------- 建议使用一个服务端,根据传输内容区别发送者的身份和处理传输的内容
如01是客房 02是餐厅 03是保安 04是总经理室 --------------------编程问答-------------------- 两个监听端口该怎么写?碰到这问题,自己搞了两三天了,都没有思路,没人带真的搞不了,求大哥们指点一下 --------------------编程问答-------------------- 嘿嘿 学习学习    多个端口  用 异步 ??? --------------------编程问答-------------------- 难道不是多new几个socket然后listen的节奏? --------------------编程问答-------------------- LZ的写法是可以实现的,只不过你写在一起的话后面的操作就比较难区分了,不过原理就是这个原理,开两个线程,分别监听两个端口。 --------------------编程问答-------------------- 想问下对于socket 如何起多个server然后再server间切换? --------------------编程问答-------------------- 开两个端口不用写两个线程,一个就够了!  我写过类似的,开启 8500 跟 8900 两个端口 --------------------编程问答-------------------- 这样写是没问题的,只是你这边完全没必要用线程去开启监听,直接在UI线程里面开启监听就可以了。
--------------------编程问答-------------------- 同问,我在服务端建立了一个全局的socket ; public  static Socket Listener_Socket; 用来监听多个端口,比如我循环下面方法开启了多个监听端口:代码如下:,当多个客户端跟服务端进行socket链接的时候,不同端口之间的客户端会相互影响,造成占用通道的情况,进入了假死状态。举个例子如:两个客户端都链接了800端口,这两个客户端就可以进行通讯。若此时,另外两个客户端链接了801端口,按理来说,链接801端口的两个客户端也可以进行通讯,而且跟800的两个正在通讯的客户端互不影响,确实这样吗?不以为然,结果是,首次链接的客户端进入800端口,他们可以进行通讯没错,但是当某一个客户端进入别的端口,如801或者其他都行,就会造成首次链接的客户端(链接800端口的客户端)通信出现障碍,是不是假死我也是猜测的,我在怀疑是不是一个socket只能建立一个监听端口?  而我如今是一个socket监听了多个端口,所有不行吗? 原因不得而知啊?
/// <summary>
        /// 启动端口
        /// </summary>
        /// <param name="Port">端口</param>
        /// <returns></returns>
        public string StartServerOn(int Port)
        {
            try
            {
                IPAddress[] AddressAr = null;
                String ServerHostName = "";

                try
                {
                    ServerHostName = Dns.GetHostName();
                    IPHostEntry ipEntry = Dns.GetHostByName(ServerHostName);
                    AddressAr = ipEntry.AddressList;
                }
                catch (Exception) { }
                if (AddressAr == null || AddressAr.Length < 1)
                {
                    return "无法获取本地地址…错误";
                }
                Listener_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                Listener_Socket.Bind(new IPEndPoint(AddressAr[0], Port));
                Listener_Socket.Listen(-1);
                Listener_Socket.BeginAccept(new AsyncCallback(EndAccept), Listener_Socket);
                return ("启动监听" + AddressAr[0].ToString() + ":" + Port + "成功!");
            }
            catch (Exception ex) { return ex.Message; }
        }  --------------------编程问答-------------------- 如果有用到10个端口,你就写10个类似
     thisListener.Bind(thisIpEndPoint);
就行了。似乎也没有什么可说的了。

--------------------编程问答-------------------- 服务器绑定IP,通常应该是 IPAddress.Any。写成 192.168.1.166 只能处理一小部分网络适配服务功能,你根本没有监听服务器上所有适配器。

既然你写了 BeginAccept(异步处理),那么你根本没有必要搞什么“线程”。你可以写,例如:
private void button1_Click(object sender, EventArgs e)
{
    ......
    this.Listener1.Bind(point1);
    this.Listener1.BeginAccept(ReceiveProcess, null);
    .....
    this.Listener2.Bind(point2);
    this.Listener2.BeginAccept(ReceiveProcess, null);
}
这就行了。不需要画蛇添足地弄两个 Thread 在这里过渡一下。


另外如果两个处理方法不同,你应该先抽象出处理方法的共同部分,例如

public abstract class ProcBase
{
    public void Process(object o)
    {
        .....
    }

    abstract Proc(...);
}

public class Proc1: ProcBase
{
    override Proc(...)
    {
         .....
    }
}

public class Proc1: ProcBase
{
    override Proc(...)
    {
         .....
    }
}
然后初始化时写
private void button1_Click(object sender, EventArgs e)
{
    ......
    this.Listener1.Bind(point1);
    var p1 = new Proc1();
    this.Listener1.BeginAccept(p1.Process, null);
    .....
    this.Listener2.Bind(point2);
    var p2 = new Proc2();
    this.Listener2.BeginAccept(p2.Process, null);
}


这样,在ProcBase中写明共通的部分,而子类仅仅写几行不一样的扩展部分。而不要过度地copy代码! --------------------编程问答-------------------- 后边 public class Proc1: ProcBase  改为  public class Proc2: ProcBase


编写服务器程序,不要写任何阻塞的代码,尤其不要写什么 MessageBox.Show 之类的代码。 --------------------编程问答-------------------- 学习学习。。
补充:.NET技术 ,  C#
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,