繁体   English   中英

如何使用tcp客户端,多端口或其他方式连接到调制解调器?

[英]How to connect to modems with tcp clients, in multiple port or other way?

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

    }

使用的类:

您需要使用异步tcp / ip方法。 本文介绍如何:

http://www.codeproject.com/KB/IP/asyncsockets.aspx

关键部分是BeginReceive()和相关的回调函数。 还有q,请在这个答案留下评论;)最好的运气!

您需要多线程,每当客户端建立与服务器的连接时,为它启动一个新线程并开始通信发送/接收。

以下是一些解释c#, sc -sharpcorner 代码项目中多线程的文章

这是一个带有多线程的示例服务器应用程序, http://www.dotnetspider.com/resources/2829-A-multi-readed-server-C-which-finds-prime-num.aspx

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM