Here's a shorter version that can be used with telent. However, this version doesn't support multiple clients. It also disconnects after a single message transmission. One adds the text <|EOM|> to the end of the message to indicate that it's the end of the message.
Here's a message example: Hello World <|EOM|>
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace SocketsTest
{
    public class Server
    {
        private async Task HandleCommunication(ListenerClient client)
        {
            //create reference
            Socket handler = client.ClientSocket;
            if (handler == null)
                return;
            //holds all data received
            byte[] cumulativeBuffer = new byte[1024];
            int bufferPosition = 0;
            //send NULL to client
            await handler.SendAsync(new byte[] { 0x00}, 0);
            //send message to client
            await handler.SendAsync(Encoding.UTF8.GetBytes("Welcome"), SocketFlags.None);
            //send CRLF (newline) to client
            await handler.SendAsync(new byte[] { 0xD, 0xA }, SocketFlags.None);
            //send message to client
            await handler.SendAsync(Encoding.UTF8.GetBytes("At the end of the message type \"<|EOM|>\" which signals"), SocketFlags.None);
            //send CRLF (newline) to client
            await handler.SendAsync(new byte[] { 0xD, 0xA }, SocketFlags.None);
            //send message to client
            await handler.SendAsync(Encoding.UTF8.GetBytes("that this is the end of the message (ie: end of the transmission)"), SocketFlags.None);
            //send CRLF (newline) to client
            await handler.SendAsync(new byte[] { 0xD, 0xA, 0xD, 0xA }, SocketFlags.None);
            //send message to client
            await handler.SendAsync(Encoding.UTF8.GetBytes("Please enter a message"), SocketFlags.None);
            //send CRLF (newline) to client
            await handler.SendAsync(new byte[] { 0xD, 0xA }, SocketFlags.None);
            while (true)
            {
                //loops each time data is received
                //when using telnet, this is when a single character has been received
                //holds the current data received
                byte[] currentDataBuffer = new byte[1024];
                //wait for data from client
                int bytesReceived = await handler.ReceiveAsync(currentDataBuffer, SocketFlags.None);
                if (bytesReceived > 0)
                {
                    //copy data received from the current data buffer to cumulative buffer
                    Buffer.BlockCopy(currentDataBuffer, 0, cumulativeBuffer, bufferPosition, bytesReceived);
                    //set value
                    bufferPosition += bytesReceived;
                    //send NULL to client; this echos (ie: displays) the input
                    await handler.SendAsync(new byte[] { 0x00 }, SocketFlags.None);
                }
                //get cumulative message
                //a message is complete when "<|EOM|>" is found
                string cumulativeMessage = Encoding.UTF8.GetString(cumulativeBuffer, 0, bufferPosition);
                string eom = "<|EOM|>";
                if (cumulativeMessage.IndexOf(eom) > -1) //is end of message
                {
                    //send CRLF (newline) to client
                    await handler.SendAsync(new byte[] { 0xD, 0xA }, SocketFlags.None);
                    string ackMessage = "<|ACK|>";
                    var echoBytes = Encoding.UTF8.GetBytes(ackMessage);
                    //send message to client 
                    await handler.SendAsync(echoBytes, SocketFlags.None);
                    //send CRLF (newline) to client
                    await handler.SendAsync(new byte[] { 0xD, 0xA }, SocketFlags.None);
                    //send message to client
                    await handler.SendAsync(Encoding.UTF8.GetBytes("Goodbye"), SocketFlags.None);
                    //send CRLF (newline) to client
                    await handler.SendAsync(new byte[] { 0xD, 0xA }, SocketFlags.None);
                    //end of message was found, so there won't be any more data
                    //exit loop
                    break;
                }
            }
        }
        public async Task Start(int portNumber, int backlog = Int32.MaxValue)
        {
            //listen on all - 0.0.0.0
            IPAddress ipAddress = IPAddress.Any;
            IPEndPoint ipEndPoint = new(ipAddress, portNumber);
            using Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            listener.Bind(ipEndPoint);
            listener.Listen(100);
            //wait for connection
            Socket handler = await listener.AcceptAsync();
            //connected to client; handle communication
            await HandleCommunication(new ListenerClient(Guid.NewGuid().ToString("N"), handler));
            handler.Shutdown(SocketShutdown.Both);
            handler.Close();      
        }
    }
    internal class ListenerClient
    {
        public Socket ClientSocket { get; private set; }
        public string Id { get; private set; }
        public DateTime ConnectedOn { get; private set; }
        public ListenerClient(string id, Socket clientSocket)
        {
            Id = id;
            ClientSocket = clientSocket;
        }
        public ListenerClient(string id, Socket clientSocket, DateTime connectedOn)
        {
            Id = id;
            ClientSocket = clientSocket;
            ConnectedOn = ConnectedOn;
        }
    }
}
Adapted from here,