Получаване на множество различни съобщения TcpListener C#

Здравейте, момчета, опитвам се да науча как да изпращам прости текстови съобщения между клиентски сървър с помощта на TcpListener и сокети. Прочетох много теми, които изглежда показват как да се чете _Buffer в, да речем, цикъл, за да се гарантира, че цялото съобщение е прочетено. Изглежда обаче не мога да разбера как да получа второто съобщение след получаване на първото. Мога да се свържа със сървъра добре и мога да получа първото съобщение съвсем добре. Ако обаче отново натисна бутона за изпращане на моя клиент, никакво съобщение не достига до сървъра. Ето моят код:

// SERVER APPLICATION: -----------------------------------------------

namespace TCP_Server { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

    private void btnStartServer_Click(object sender, EventArgs e)
    {
        // Define the TCP Listner:
        TcpListener _listner = new TcpListener(IPAddress.Parse("127.0.0.1"), 7777);

        // Start The Listner:
        _listner.Start();

        //Show the server is now listening:
        listStatus.Items.Add("Server started - Listening on port 7777");

        //Create a socket to accept - This is a Blocking Call:
        Socket _sock = _listner.AcceptSocket();

        //When Client Connects show server has accepted the socket:
        listStatus.Items.Add("User from IP " + _sock.RemoteEndPoint);

        while (_sock.Connected)
        {

            // Create Byte to Receive Data:
            byte[] _Buffer = new byte[1024];

            // Create integer to hold how large the Data Received is:
            int _DataReceived = _sock.Receive(_Buffer);

            // Lets Server Know Message is Received:
            listStatus.Items.Add("Message Received...");

            // Convert Buffer to a String:
            string _Message = Encoding.ASCII.GetString(_Buffer);

            // Post Message to the Server Window:
            listStatus.Items.Add(_Message);

            _sock.Close();
        }
    }
}

}

// CLIENT APPLICATION: ----------------------------------------------------

namespace TCP__Client { public partial class Form1 : Form { public Form1() { InitializeComponent(); }

// Defind the TCP Client: TcpClient _Client = new TcpClient(); private void btnConnect_Click(object sender, EventArgs e) { // Connect the TCP Client: _Client.Connect("127.0.0.1", 7777); // Show the Client has Connected: listStatus.Items.Add("Connected to Server 127.0.0.1"); } private void btnSend_Click(object sender, EventArgs e) { while (_Client.Connected) { // Create a Stream: Stream _Stream = _Client.GetStream(); // Create Instance of an Encoder: ASCIIEncoding _Asc = new ASCIIEncoding(); byte[] _Buffer = new byte[1024]; // Create Buffer to Send Message: _Buffer = _Asc.GetBytes(txtMessage.Text); // Show Client is Sending Message: listStatus.Items.Add("Tranmitting Message..."); // Write Message to the Stream: _Stream.Write(_Buffer, 0, _Buffer.Length); // Close Stream _Stream.Close(); _Stream.Dispose(); } } }

}

Ще съм много благодарен, ако някой може да обясни как да направя това, за да мога да получа повече от едно съобщение. Имам малко опит в използването на Задачи и нишки, това ли е нещо, което трябва да направя? Просто се опитвам да разбера това, за да мога да започна да го уча. Ако някой има препоръки или примери, които смятате, че могат да помогнат, моля, споделете.


person Timg    schedule 12.01.2014    source източник
comment
Незатварянето на гнездото в края на цикъла би било добро начало. Как очаквате да получите повече байтове, ако затворите сокета? Също така имайте предвид: „байтове“, а не „съобщение“. TCP сам по себе си не може да прехвърля „съобщения“, по-дълги от един байт.   -  person Martin James    schedule 12.01.2014


Отговори (1)


Докато клиентът все още е свързан към сървъра, не затваряйте съзнателно гнездото на сървърното приложение. Тъй като трябва да поддържате връзката жива, за да получите друго съобщение, повторете извикването на функцията за получаване. Ако няма изпратени данни от клиента, извикването на функцията Receive() автоматично ще блокира текущата ви нишка, за да изчака наличните данни. Ако щракнете отново върху изпращане на съобщение в клиентското приложение, данните ще бъдат достъпни за сървъра и ще деблокират тази блокираща част в сървърното приложение.

Вашето сървърно приложение може да блокира потребителския интерфейс на частта AcceptSocket() и Receive(). Когато се щракне върху бутона StartServer, прозорецът на вашия сървър (UI) може да не отговаря поради липса на налична входяща връзка и не можете да видите съобщения в контролата на състоянието на списъка. По този начин е по-добре да поставите тези части от кода на Socket да се изпълняват в отделна нишка, за да не блокирате нишката на потребителския интерфейс. За да работите върху компонента на потребителския интерфейс от отделната нишка, е необходима манипулация на потребителския интерфейс, безопасна за нишката.

Ето промените, които направих:

сървър

namespace Tcp_Server
{
    public partial class Form1 : Form
    {
        delegate void AddTextCallback(string text);

        public Form1()
        {
            InitializeComponent();
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(ServerHandler));
        }

        private void ServerHandler(object args)
        {
            TcpListener _listner = new TcpListener(IPAddress.Parse("127.0.0.1"), 7777);

            // Start The Listner:
            _listner.Start();

            //Show the server is now listening (Note: UI Thread-Safe is required):
            AddText("Server started - Listening on port 7777");

            //Create a socket to accept - This is a Blocking Call:
            Socket _sock = _listner.AcceptSocket();

            //When Client Connects show server has accepted the socket:
            AddText("User from IP " + _sock.RemoteEndPoint);

            while (_sock.Connected)
            {

                // Create Byte to Receive Data:
                byte[] _Buffer = new byte[1024];

                // Create integer to hold how large the Data Received is:
                int _DataReceived = _sock.Receive(_Buffer);

                if (_DataReceived == 0)
                {
                    // Socket has been shutdown by the client.
                    break;
                }

                // Lets Server Know Message is Received:
                AddText("Message Received...");

                // Convert Buffer to a String:
                string _Message = Encoding.ASCII.GetString(_Buffer);

                // Post Message to the Server Window:
                AddText(_Message);
            }

            _sock.Close();
            //When Client disconnect from the server:
            AddText("Client Disconnected.");

            _listner.Stop();
            AddText("Server Stop.");
        }


        private void AddText(string text)
        {
            // InvokeRequired required compares the thread ID of the 
            // calling thread to the thread ID of the creating thread. 
            // If these threads are different, it returns true. 
            if (this.listStatus.InvokeRequired)
            {
                AddTextCallback d = new AddTextCallback(AddText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.listStatus.Items.Add(text);
            }
        }
    }
}

Клиент

namespace Tcp_Client
{
    public partial class Form1 : Form
    {
        // Defind the TCP Client:
        TcpClient _Client = null;
        Stream _Stream = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            _Client = new TcpClient();

            // Connect the TCP Client:
            _Client.Connect("127.0.0.1", 7777);

            // Show the Client has Connected:
            listStatus.Items.Add("Connected to Server 127.0.0.1");

            // Create a Stream:                
            _Stream = _Client.GetStream();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (_Client.Connected)
            {
                // Create Instance of an Encoder:
                ASCIIEncoding _Asc = new ASCIIEncoding();

                byte[] _Buffer = new byte[1024];

                // Create Buffer to Send Message:
                _Buffer = _Asc.GetBytes(txtMessage.Text);

                // Show Client is Sending Message:
                listStatus.Items.Add("Tranmitting Message...");

                // Write Message to the Stream:
                _Stream.Write(_Buffer, 0, _Buffer.Length);
            }
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            _Stream.Close();
            _Stream.Dispose();
            _Client.Close();
            listStatus.Items.Add("Disconnected from server.");
        }
    }
}
person Darius Iko    schedule 12.01.2014
comment
Перфектно, което работи Страхотно... И още по-добре, дори разбрах за какво говориш хаха. Оценявам помощта. - person Timg; 14.01.2014