• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

LuBoc

Terminar correctamente um TCP Listener

4 mensagens neste tópico

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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros 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 { }
                       
                      
        }

     }
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Olá apocsantos,

Agradeço a resposta.

Para a tua solução tive que adicionar clientStream e tcpClient ao Global methods.

Agora já termina correctamente.

Obrigado,

LB

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros 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

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora