简体   繁体   English

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

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

I have around 5000 modem (thin clients), and I want to communicate with them, one of a my method is like this : string GetModemData(modemID) , now I have an open port in server that listens to modem and I'm using socket programming to send data to modems (calling related function), but when i want send data to multiple modem in a same time and get response from them, I don't know what should i do? 我有大约5000个调制解调器(瘦客户端),我想与他们通信,我的方法之一是这样的: string GetModemData(modemID) ,现在我有一个服务器中的开放端口,监听调制解调器,我正在使用socket编程将数据发送到调制解调器(调用相关函数),但是当我想在同一时间向多个调制解调器发送数据并从中获取响应时,我不知道该怎么办? I can send data to one modem and waiting for its response and then send another data to other modems (sequential), but the problem is client should be wait long time to get answer(may be some different client want to get some information from modems so they all will be wait into the Q or something like this), I think one way to solving this problem is to use multiple port and listen for each modem to related port, but it takes too many ports and also may be memory usage going up and exceed my available memory space, so some lost may be occurred (is this true?). 我可以将数据发送到一个调制解调器并等待其响应,然后将其他数据发送到其他调制解调器(顺序),但问题是客户端应该等待很长时间才能得到答案(可能是某些不同的客户端希望从调制解调器获取一些信息所以他们都会等到Q或类似的东西),我认为解决这个问题的一种方法是使用多个端口并监听每个调制解调器到相关的端口,但它需要太多的端口,也可能是内存使用量up并超过我的可用内存空间,因此可能会发生一些丢失(这是真的吗?)。 what should to do ? 该怎么办? I'd thinking about Parallelism, but i think its not related i should to wait for one port, because i don't know should to pass current received data to which client. 我考虑并行,但我认为它不相关我应该等待一个端口,因为我不知道应该将当前接收的数据传递给哪个客户端。 I'm using asp.net. 我正在使用asp.net。

currently I'm doing like this: 目前我这样做:

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

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

and in return 作为回报

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????
}

and : 并且:

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) 
            {
            }
        }

Heres an example keeping track of all your clients. 这是一个跟踪所有客户的例子。 I've compacted it for readability. 为了便于阅读,我已经压缩了它。 You should really split it up into multiple classes. 你应该把它分成多个类。

I'm using Pool (which I just created and commited) and SimpleServer. 我正在使用Pool(我刚创建并提交)和SimpleServer。 Both classes are part of a library that I'm currently building (but far from done). 这两个类都是我正在构建的库的一部分(但远未完成)。

Don't be afraid of having 5000 sockets open, they do not consume much resources when you are using asynchronous operations. 不要害怕打开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;
        }

    }

Used classes: 使用的类:

You need to use the asynchronous tcp/ip methods. 您需要使用异步tcp / ip方法。 This article shows how: 本文介绍如何:

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

The critical piece is the BeginReceive() and related callback functions. 关键部分是BeginReceive()和相关的回调函数。 Any more q's, please leave comments to this answer ;) BEST OF LUCK! 还有q,请在这个答案留下评论;)最好的运气!

You need multi threading, whenever a client establishes a connection to the server start a new thread for it and start communication send/receive. 您需要多线程,每当客户端建立与服务器的连接时,为它启动一个新线程并开始通信发送/接收。

Here are some articles explaining multithreading in c#, c-sharpcorner codeproject 以下是一些解释c#, sc -sharpcorner 代码项目中多线程的文章

And here's a sample server application with multithreading, http://www.dotnetspider.com/resources/2829-A-multi-readed-server-C-which-finds-prime-num.aspx 这是一个带有多线程的示例服务器应用程序, 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