A full-duplex communication protocol implemented by C#.net TcpClient

First understand TCP, also known as the three-way handshake protocol, that is, the first time to confirm whether the server can connect, the second time to send information to the server, and then the server responds, and so on repeatedly. At this time, you find that it seems that only the client can send me Information, I can’t send information to the client, but sometimes I need to send information to the client, so don’t talk nonsense and go directly to the code

What did the server and the client do? The server first saves the connection of the client. Yes, the connection between the client and the server can be saved. There is no need to interrupt the connection every time. At this time, use If the saved connection is used for subsequent communication, the client will automatically send an interruption message to the server after 2 minutes. At this time, it will be removed from the queue. At this time, the client will complete its mission.

Function introduction, the server will send a Holle to the client every 20 seconds, the client can send information on the console, this information can be seen by other clients, then the client will send it directly to the server after 2 minutes Instruction, I want to end the connection. At this time, the server closes the connection. This time, the client has completed its mission.

server code server

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System. Text;
using System. Threading;

class Program
{
    static List<TcpClient> clients = new List<TcpClient>();

    static void Main(string[] args)
    {
        // Create a server Socket and listen to port 8080 of the local IP address
        TcpListener listener = new TcpListener(IPAddress. Parse("127.0.0.1"), 8080);
        listener. Start();

        Console.WriteLine("The server is started, waiting for the client to connect...");

        // Create a timer and send a message to all clients every 20 seconds
        Timer timer = new Timer(SendHelloMessage, null, TimeSpan. Zero, TimeSpan. FromSeconds(20));

        while (true)
        {
            // Accept the client connection request and create a new TcpClient object
            TcpClient client = listener.AcceptTcpClient();

            Console.WriteLine("The client is connected: {0}", client.Client.RemoteEndPoint);

            // add the client to the list
            clients. Add(client);

            // send data to client
            byte[] buffer = Encoding.UTF8.GetBytes("Hello, client!");
            NetworkStream stream = client. GetStream();
            stream.Write(buffer, 0, buffer.Length);

            // Start the thread and receive client messages
            ThreadPool. QueueUserWorkItem(ReceiveMessage, client);
        }
    }

    static void SendHelloMessage(object state)
    {
        foreach (TcpClient client in clients)
        {
            try
            {
                byte[] buffer = Encoding.UTF8.GetBytes("Hello!");
                NetworkStream stream = client. GetStream();
                stream.Write(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                // Send failed, remove the client from the list
                Console.WriteLine("Failed to send message to client {0}: {1}", client.Client.RemoteEndPoint, ex.Message);
                clients. Remove(client);
            }
        }
    }

    static void ReceiveMessage(object state)
    {
        TcpClient client = (TcpClient) state;
        NetworkStream stream = client. GetStream();

        while (true)
        {
            byte[] buffer = new byte[1024];
            int count = stream. Read(buffer, 0, buffer. Length);

            if (count == 0)
            {
                // client has closed the connection
                Console.WriteLine("The client has closed the connection: {0}", client.Client.RemoteEndPoint);
                clients. Remove(client);
                break;
            }

            string message = Encoding.UTF8.GetString(buffer, 0, count);
            Console.WriteLine("Received client message: {0}", message);

            if (message == "keepAlive")
            {
                // The client sends a heartbeat command and closes the connection
                Console.WriteLine("The client sent a heartbeat command, close the connection: {0}", client.Client.RemoteEndPoint);
                clients. Remove(client);
                client.Close();
                break;
            }

            // broadcast message to all clients
            foreach (TcpClient c in clients)
            {
                if (c == client)
                {
                    continue;
                }

                buffer = Encoding.UTF8.GetBytes(message);
                c.GetStream().Write(buffer, 0, buffer.Length);
            }
        }
    }
}

Client code Client

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System. Text;
using System. Threading;

class Program
{
    static void Main(string[] args)
    {
        // Create a client Socket, connect to the IP address and port of the server
        TcpClient client = new TcpClient("127.0.0.1", 8080);
        byte[] buffer = new byte[1024];

        // Get the input and output stream of the client
        NetworkStream stream = client. GetStream();

        Task.Factory.StartNew(() => { Write(stream); });


        // Start the thread and send an instruction to the server every 2 minutes
        ThreadPool. QueueUserWorkItem(SendInstruction, client);

        while (true)
        {
            //Read the user input data and send it to the server
            string sendMsg = Console.ReadLine();//Send information to the server
            buffer = Encoding.UTF8.GetBytes(sendMsg);//Convert the input information into information that the server can understand, and then send it to the server
            stream.Write(buffer, 0, buffer.Length);//Send information to the server
        }
    }

    /// <summary>
    /// Obtain the information sent by the server, and then display it on the page
    /// </summary>
    /// <param name="state"></param>
    static void Write(NetworkStream stream)
    {
        while (true)
        {
            // read the data sent by the server
            byte[] buffer = new byte[1024];
            int count = stream. Read(buffer, 0, buffer. Length);
            string message = Encoding.UTF8.GetString(buffer, 0, count);
            Console.WriteLine("Received server message: {0}", message);
        }
    }


    static void SendInstruction(object state)
    {
        TcpClient client = (TcpClient) state;
        NetworkStream stream = client. GetStream();

        while (true)
        {
            // Send a command to the server every 2 minutes
            Thread. Sleep(122000);
            string instruction = "keepAlive";
            byte[] buffer = Encoding.UTF8.GetBytes(instruction);
            try
            {
                stream.Write(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                Console.WriteLine("The server is disconnected");
                break;
            }
        }
    }
}