Jump to content

Terminar correctamente um TCP Listener


LuBoc
 Share

Recommended Posts

Olá,

Tenho esta pequena aplicação:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace gpsReader
{
    public partial class GpsReader : Form
    {

        // Global methods
        private static TcpListener tcpListener;
        private static Thread listenThread;
        private string endl = "\r\n";        

        public GpsReader()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Botão ler dados. Inicia/Para a leitura da porta especificada
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btReader_Click(object sender, EventArgs e)
        {
            try
            {
                if (btReader.Text == "Stop!")
                {
                    listenThread.Abort();
                    btReader.Text = "Ler Dados";
                }
                else
                {
                    btReader.Text = "Stop!";
                    tcpListener = new TcpListener(IPAddress.Any, (int)PortNumber.Value);
                    listenThread = new Thread(new ThreadStart(ListenForClients));
                    listenThread.Start();
                }
            }
            catch (Exception err)
            {
                GpsData.AppendText("Erro: " + err.Message);
                GpsData.AppendText(endl); 
                listenThread.Abort(); 
                btReader.Text = "Ler Dados"; 
            }
            finally {  }
        }

        /// <summary>
        /// Listens for client connections
        /// </summary>
        protected void ListenForClients()
        {
            tcpListener.Start();

            while (true)
            {
                try
                {
                    // Blocks until a client has connected to the server
                    TcpClient client = tcpListener.AcceptTcpClient();

                    // Create a thread to handle communication with connected client
                    Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                    clientThread.Start(client);
                }
                catch (Exception err)
                {
                    GpsData.AppendText("Erro: " + err.Message);
                    GpsData.AppendText(endl);
                }
            }
        }

        /// <summary>
        /// Handles client connections
        /// </summary>
        /// <param name="client"></param>
        protected void HandleClientComm(object client)
        {
            //int NumBytes = 4096;
            int NumBytes = 256;

            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[NumBytes];
            int bytesRead;

            do
            {
                bytesRead = 0;

                try
                {
                    // Blocks until a client sends a message                    
                    bytesRead = clientStream.Read(message, 0, NumBytes);
                }
                catch (Exception err)
                {
                    // A socket error has occured
                    GpsData.AppendText("Erro: " + err.Message);
                    GpsData.AppendText(endl);
                    break;
                }

                if (bytesRead == 0)
                {
                    // The client has disconnected from the server
                    break;
                }

                // Message has successfully been received
                ASCIIEncoding encoder = new ASCIIEncoding();

                //-- Colocar na caixa de mensagem
                GpsData.AppendText(encoder.GetString(message, 0, bytesRead));                
                GpsData.AppendText(endl);
                

            } while (clientStream.DataAvailable);

            // Release connections
            clientStream.Close();
            tcpClient.Close();
        }

        private void btTerminar_Click(object sender, EventArgs e)
        {
            try
            {
                tcpListener.Stop();
                listenThread.Abort();
            }
            catch { }
                        
            Application.Exit();            
        }

     }
}

(Nota: Falta a parte visual do formulário)

O qual faz o listening de uma porta TCP, registado tudo numa richTextBox.

Acontece que quando pressiono o botão "Terminar", a aplicação é fechada, mas se for ao Task Manager (Gestor de Tarefas), aparece a aplicação, e se executar novamente dá o erro de porta já estar a ser usada.

Então qual a forma correcta de terminar a aplicação ? Que código devo colocar em private void btTerminar_Click(object sender, EventArgs e) ?

Agradeço a ajuda.

Cumprimentos,

LB

Link to comment
Share on other sites

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace gpsReader
{
    public partial class GpsReader : Form
    {

        // Global methods
        private static TcpListener tcpListener;
        private static Thread listenThread;
        private string endl = "\r\n";       

        public GpsReader()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Botão ler dados. Inicia/Para a leitura da porta especificada
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btReader_Click(object sender, EventArgs e)
        {
            try
            {
                if (btReader.Text == "Stop!")
                {
                    listenThread.Abort();
                    btReader.Text = "Ler Dados";
                }
                else
                {
                    btReader.Text = "Stop!";
                    tcpListener = new TcpListener(IPAddress.Any, (int)PortNumber.Value);
                    listenThread = new Thread(new ThreadStart(ListenForClients));
                    listenThread.Start();
                }
            }
            catch (Exception err)
            {
                GpsData.AppendText("Erro: " + err.Message);
                GpsData.AppendText(endl);
                listenThread.Abort();
                btReader.Text = "Ler Dados";
            }
            finally {  }
        }

        /// <summary>
        /// Listens for client connections
        /// </summary>
        protected void ListenForClients()
        {
            tcpListener.Start();

            while (true)
            {
                try
                {
                    // Blocks until a client has connected to the server
                    TcpClient client = tcpListener.AcceptTcpClient();

                    // Create a thread to handle communication with connected client
                    Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                    clientThread.Start(client);
                }
                catch (Exception err)
                {
                    GpsData.AppendText("Erro: " + err.Message);
                    GpsData.AppendText(endl);
                }
            }
        }

        /// <summary>
        /// Handles client connections
        /// </summary>
        /// <param name="client"></param>
        protected void HandleClientComm(object client)
        {
            //int NumBytes = 4096;
            int NumBytes = 256;

            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[NumBytes];
            int bytesRead;

            do
            {
                bytesRead = 0;

                try
                {
                    // Blocks until a client sends a message                   
                    bytesRead = clientStream.Read(message, 0, NumBytes);
                }
                catch (Exception err)
                {
                    // A socket error has occured
                    GpsData.AppendText("Erro: " + err.Message);
                    GpsData.AppendText(endl);
                    break;
                }

                if (bytesRead == 0)
                {
                    // The client has disconnected from the server
                    break;
                }

                // Message has successfully been received
                ASCIIEncoding encoder = new ASCIIEncoding();

                //-- Colocar na caixa de mensagem
                GpsData.AppendText(encoder.GetString(message, 0, bytesRead));               
                GpsData.AppendText(endl);
               

            } while (clientStream.DataAvailable);

            // Release connections
            clientStream.Close();
            tcpClient.Close();
        }

        private void btTerminar_Click(object sender, EventArgs e)
        {
            try
            {
                clientStream.Close();
                tcpClient.Close();
                tcpListener.Stop();
                listenThread.Abort();
                Application.Exit();            
      }
            catch { }
                       
                      
        }

     }
}

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Link to comment
Share on other sites

Eu não testei o código, apenas li e vi onde me parecia estar a faltar algo, segundo o sintoma que indicas-te ele estaria a manter a porta ocupada, o que me deu a entender que faltava que a tua app indica-se ao SO que já não estava mais "na escuta" naquela porta, libertando-a.

Mas como disse, não testei o código! daí ter falhado e não ter posto codigo 100% correcto. Pelo que peço desculpas.

António

"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.