我有大约5000个调制解调器(瘦客户端),我想与他们通信,我的方法之一是这样的:string GetModemData(modemID),现在我在服务器中有一个开放的端口可以监听调制解调器,并且我正在使用套接字编程来发送数据到调制解调器(调用相关功能),但是当我想同时将数据发送到多个调制解调器并获得它们的响应时,我不知道该怎么办?我可以将数据发送到一个调制解调器并等待其响应,然后将另一数据发送到其他调制解调器(顺序),但是问题是客户端应该等待很长时间才能获得答案(可能是某些不同的客户端想要从调制解调器获取一些信息)所以他们都会等到Q或类似的东西),我认为解决此问题的一种方法是使用多个端口并监听每个调制解调器到相关的端口,但是它占用了太多的端口,并且可能还会占用内存超过我的可用内存空间,因此可能会发生一些丢失(这是真的吗?)。该怎么办?我在考虑并行性,但是我认为与并行性无关,我应该等待一个端口,因为我不知道应该将当前接收到的数据传递给哪个客户端。我正在使用asp.net。

目前我正在这样做:

private void StartListener()
    {
        ModemTcpListener = new TcpListener(ModemPort);
        //ClientTcpListener = new TcpListener(ClientPort);

        ModemTcpListener.Start();
        ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
    }

作为返回
private void DoReadModemCallback(IAsyncResult ar)
         {
             try
             {
                 bool bRet = ar.AsyncWaitHandle.WaitOne(420000);
                 Modem modem = ar.AsyncState as Modem;
                 if (!bRet || modem == null)
                 {
                     return;
                 }
           }
           catch{}
            // now send data to which client?????? if i'm going to use async????
}

和 :
private void DoAcceptModemCallback(IAsyncResult ar)
        {
            try
            {
                ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
                TcpClient tcpClient = ModemTcpListener.EndAcceptTcpClient(ar);
                Modem modem= new Modem(tcpClient, "");
                tcpClient.GetStream().BeginRead(modem.Buffer, 0, tcpClient.ReceiveBufferSize, new AsyncCallback(DoReadModemCallback), modem);
                ModemTcpListener.BeginAcceptTcpClient(new AsyncCallback(DoAcceptModemCallback), ModemTcpListener);
                Log.Write("a Modem connect ...");
            }
            catch (Exception ex)
            {
            }
        }

最佳答案

这是一个跟踪所有客户的示例。我将其压缩以提高可读性。您实际上应该将其分为多个类。

我正在使用Pool(我刚刚创建并提交)和SimpleServer。这两个类都是我当前正在构建的库的一部分(但远未完成)。

不要担心会打开5000个套接字,当您使用异步操作时,它们不会消耗太多资源。

    public class SuperServer
    {
        private List<ClientContext> _clients = new List<ClientContext>();
        private SimpleServer _server;
        private Pool<byte[]> _bufferPool;

        public SuperServer()
        {
            // Create a buffer pool to be able to reuse buffers
            // since your clients will most likely connect and disconnect
            // often.
            //
            // The pool takes a anonymous function which should return a new buffer.
            _bufferPool = new Pool<byte[]>(() => new byte[65535]);
        }

        public void Start(IPEndPoint listenAddress)
        {
            _server = new SimpleServer(listenAddress, OnAcceptedSocket);

            // Allow five connections to be queued (to be accepted)
            _server.Start(5);
        }

        // you should handle exceptions for the BeginSend
        // and remove the client accordingly.
        public void SendToAll(byte[] info)
        {
            lock (_clients)
            {
                foreach (var client in _clients)
                    client.Socket.BeginSend(info, 0, info.Length, SocketFlags.None, null, null);
            }
        }

        // Server have accepted a new client.
        private void OnAcceptedSocket(Socket socket)
        {
            var context = new ClientContext();
            context.Inbuffer = _bufferPool.Dequeue();
            context.Socket = socket;

            lock (_clients)
                _clients.Add(context);

            // this method will eat very few resources and
            // there should be no problem having 5000 waiting sockets.
            context.Socket.BeginReceive(context.Inbuffer, 0, context.Inbuffer.Length, SocketFlags.None, OnRead,
                                        context);
        }

        //Woho! You have received data from one of the clients.
        private void OnRead(IAsyncResult ar)
        {
            var context = (ClientContext) ar.AsyncState;
            try
            {
                var bytesRead = context.Socket.EndReceive(ar);
                if (bytesRead == 0)
                {
                    HandleClientDisconnection(context);
                    return;
                }

                // process context.Inbuffer here.
            }
            catch (Exception err)
            {
                //log exception here.
                HandleClientDisconnection(context);
                return;
            }

            // use a new try/catch to make sure that we start
            // read again event if processing of last bytes failed.
            try
            {
                context.Socket.BeginReceive(context.Inbuffer, 0, context.Inbuffer.Length, SocketFlags.None, OnRead,
                                            context);
            }
            catch (Exception err)
            {
                //log exception here.
                HandleClientDisconnection(context);
            }
        }

        // A client have disconnected.
        private void HandleClientDisconnection(ClientContext context)
        {
            _bufferPool.Enqueue(context.Inbuffer);
            try
            {
                context.Socket.Close();
                lock (_clients)
                    _clients.Remove(context);
            }
            catch(Exception err)
            {
                //log exception
            }
        }


        // One of your modems
        // add your own state info.
        private class ClientContext
        {
            public byte[] Inbuffer;
            public Socket Socket;
        }

    }

二手课:
  • 池:http://fadd.codeplex.com/SourceControl/changeset/view/58858#1054902
  • SimpleServer:http://fadd.codeplex.com/SourceControl/changeset/view/58859#1054893
  • 关于c# - 如何通过tcp客户端以多个端口或其他方式连接到调制解调器?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4036251/

    10-12 00:18