简体   繁体   中英

Manage several/multiple tcp connections

I have a server application and client application with the functionality already working. Let me show you how I connect my client application to my server app:

                              //SERVER
           //  instantiate variables such as tempIp, port etc...
           //  ...
           // ...    

            server = new TcpListener(tempIp, port); //tempIp is the ip address of the server.

            // Start listening for client requests.
            server.Start();

            // Buffer for reading data
            Byte[] bytes = new Byte[MaxChunkSize];
            String data = null;


            // Enter the listening loop.
            while (disconect == false)
            {
                Console.Write("Waiting for a connection... ");

                // Perform a blocking call to accept requests.
                // You could also user server.AcceptSocket() here.
                client = server.AcceptTcpClient(); // wait until a client get's connected...
                Console.WriteLine("Connected!");

                // Get a stream object for reading and writing
                stream = client.GetStream();

                // now that the connection is established start listening though data
               // sent through the stream..
                int i;
                try
                {
                    // Loop to receive all the data sent by the client.
                    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {

                        // Translate data bytes to a ASCII string.
                        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                        Console.WriteLine("Received: {0}", data);
                       // etc..
                       ....

ok now on the client side lets say I want to establish a connection then send some data through the stream

                           //Client
            client = new TcpClient(serverIP, port);

            // Get a client stream for reading and writing.
            stream = client.GetStream();

            //then if I wish to send the string hello world to the server I would do:
            sendString(stream, "Hello world");


     protected void sendString(NetworkStream stream, string str)
    {
        sendBytes(stream, textToBytes(str));
    }

    protected void sendBytes(NetworkStream stream, Byte[] data)
    {
        // Send the message to the connected TcpServer. 
        stream.Write(data, 0, data.Length);
    }
    protected static Byte[] textToBytes(string text)
    {
        return System.Text.Encoding.ASCII.GetBytes(text);
    }

since I am able to send bytes I am able to send files or everything that I want. the technique that I use is that if I send the string file for example to the server then the server will start listening for a file. It will open a stream and write the received bytes to that file. If a different keyword is send the server will start listening on a different method etc..

So when dealing with one server and one client everything works great. Now I want to add more clients and need them to also connect to the server. I know that several connections can be establish on the same port just like we do it with por 80 on websites... I do not know how to manage several connections. so one thing I was thinking was to leave everything as it is. if a connection is established then tell the server to start another thread listening for other connections on the same port. with this technique I will have several threads running plus I just know the basics of multrythreading. If this technique is my best option I will start implementing it. You guys out there are really knowledgeable about all this so it will be nice if someone can point me on the right direction. Or maybe I should listen on several ports. if the server is already connected on port 7777 for example then do not accept connections from that port and start listening on port 7778 for example. I mean there could be so many different ways of achieving what I need and you guys probably know the best way. I just know the basics of networking...

You could implement a class that encapsulates TCP behavior. Check this class:

public class SimpleListener
{
    private System.Net.Sockets.TcpListener _tcpListen;
    //declare delegate to handle new connections
    public delegate void _new_client(System.Net.Sockets.TcpClient tcpclient);

    //declare a clients container (or something like...). OPTION 1
    List<System.Net.Sockets.TcpClient> _connected_clients;

    //declare an event and event handler (the same for _new_client) for new connections OPTION 2
    public event _new_client new_tcp_client;



    //public (The list of connected clients).
    public List<System.Net.Sockets.TcpClient> ConnectedClients { get { return _connected_clients; } }


    public SimpleListener(string ip, int listenport)
    {
        System.Net.IPAddress ipAd = System.Net.IPAddress.Parse(ip);
        _tcpListen = new System.Net.Sockets.TcpListener(new System.Net.IPEndPoint(ipAd,listenport));
        _connected_clients = new List<System.Net.Sockets.TcpClient>();
    }

    //Fire this method to start listening...
    public void Listen()
    {
        _tcpListen.Start();
        _set_listen();
    }
    //... and this method to stop listener and release resources on listener
    public void Stop()
    {
        _tcpListen.Stop();
    }

    //This method set the socket on listening mode... 
    private void _set_listen()
    {
        //Let's do it asynchronously - Set the method callback, with the same definition as delegate _new_client
        _tcpListen.BeginAcceptTcpClient(new AsyncCallback(_on_new_client), null);
    }



    //This is the callback for new clients
    private void _on_new_client(IAsyncResult _async_client)
    {
        try
        {
            //Lets get the new client...
            System.Net.Sockets.TcpClient _tcp_cl = _tcpListen.EndAcceptTcpClient(_async_client);
            //Push the new client to the list
            _connected_clients.Add(_tcp_cl);
           //OPTION 2 : Fire new_tcp_client Event - Suscribers will do some stuff...
            if (new_tcp_client != null) 
            {
                new_tcp_client(_tcp_cl);
            }
            //Set socket on listening mode again... (and wait for new connections, while we can manage the new client connection)
            _set_listen();
        }
        catch (Exception ex)
        {
           //Do something...or not
        }
    }

}

You could use this in your code:

                        //SERVER
       //  instantiate variables such as tempIp, port etc...
       //  ...
       // ...    

        SimpleListener server = new SimpleListener(tempIp, port); //tempIp is the ip address of the server.
        //add handler for new client connections
        server.new_tcp_client += server_new_tcp_client;
        // Start listening for client requests.
        server.Listen();
        .... //No need to loop. The new connection is handled on server_new_tcp_client method



    void server_new_tcp_client(System.Net.Sockets.TcpClient tcpclient)
{
     // Buffer for reading data
            Byte[] bytes = new Byte[MaxChunkSize];
            String data = null;
            Console.WriteLine("Connected!");

                // Get a stream object for reading and writing
            System.IO.Stream stream = tcpclient.GetStream();

               // now that the connection is established start listening though data
               // sent through the stream..
                int i;
                try
                {
                    // Loop to receive all the data sent by the client.
                    while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
                    {

                        // Translate data bytes to a ASCII string.
                        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                        Console.WriteLine("Received: {0}", data);
                       // etc..
                       ....
}

You could use threading:

var client = server.AcceptTcpClient();
var t = new Thread(new ParameterizedThreadStart(AccentClient));
t.Start(client);

The target method would look like this

public void AccentClient(object clientObj)
{
    var client = clientObj as TcpClient;

    // Do whatever you need to do with the client
}

If you are not familiar with multithreading, it is important you learn at least the basics first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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