Jump to content

Problema com ficheiros .csv em Projeto de Sistemas Distribuídos com Sockets


Luis Briga

Recommended Posts

O meu nome é Luís e estou neste momento a desenvolver um projeto que consiste na implementação de um sistema cliente/servidor para gestão de serviços de mobilidade oferecidos pela empresa ServiMoto. Os serviços incluem verificações de árvores e jardins, intervenções de bombeiros, entregas postais e entrega de pizza. O sistema permite que clientes (bicicletas) se conectem ao servidor para receber tarefas, atualizar o status das tarefas e solicitar novas tarefas. O servidor gerencia essas solicitações, aloca tarefas aos clientes e mantém registros das tarefas e clientes alocados em arquivos CSV. O projeto é implementado em C# utilizando soquetes e o protocolo de comunicação definido.

Atualmente meus dois códigos principais são estes:

classe servidor: 
 

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

class Servidor
{
    // Objeto Mutex para garantir acesso exclusivo aos arquivos CSV
    static Mutex mutex = new Mutex();

    // Método para atualizar o arquivo CSV com a conclusão de uma tarefa
    static void AtualizarTarefaConcluida(string nomeArquivo, string idTarefa)
    {
        mutex.WaitOne();
        try
        {
            string[] linhas = File.ReadAllLines(nomeArquivo);
            for (int i = 0; i < linhas.Length; i++)
            {
                if (linhas[i].StartsWith(idTarefa))
                {
                    // Substitui "em curso" por "concluída" apenas se "em curso" estiver presente
                    if (linhas[i].Contains("em curso"))
                    {
                        linhas[i] = linhas[i].Replace("em curso", "concluida");
                    }
                    break;
                }
            }
            File.WriteAllLines(nomeArquivo, linhas);
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }

    // Método para atribuir uma nova tarefa ao cliente e atualizar o arquivo CSV correspo ndente
    static void AlocarNovaTarefa(string nomeArquivo, string idCliente)
    {
        mutex.WaitOne();
        try
        {
            // Lógica para atribuir uma nova tarefa ao cliente e atualizar o arquivo CSV
            // Por exemplo, pode envolver a leitura do arquivo para encontrar uma tarefa disponível e atualizar seu status
        }
        finally
        {
            mutex.ReleaseMutex();
        }
    }

    static void Main(string[] args)
    {
        TcpListener servidor = null;
        try
        {
            // Endereço IP e porta do servidor
            IPAddress enderecoIp = IPAddress.Parse("127.0.0.1");
            int porta = 8888;

            // Inicia o servidor e escuta por conexões
            servidor = new TcpListener(enderecoIp, porta);
            servidor.Start();

            Console.WriteLine("Servidor iniciado...");

            while (true)
            {
                // Aceita a conexão do cliente
                TcpClient cliente = servidor.AcceptTcpClient();
                Console.WriteLine("Cliente conectado!");

                // Prepara as streams de rede
                NetworkStream stream = cliente.GetStream();
                byte[] dados = new byte[256];
                StringBuilder resposta = new StringBuilder();

                int bytes;

                // Lê os dados recebidos do cliente
                while ((bytes = stream.Read(dados, 0, dados.Length)) != 0)
                {
                    resposta.Append(Encoding.ASCII.GetString(dados, 0, bytes));
                    Console.WriteLine("Mensagem recebida: {0}", resposta.ToString());

                    // Verifica o tipo de mensagem recebida
                    if (resposta.ToString().StartsWith("CONNECT"))
                    {
                        // Responde com sucesso
                        byte[] msg = Encoding.ASCII.GetBytes("100 OK");
                        stream.Write(msg, 0, msg.Length);
                        Console.WriteLine("Resposta enviada: 100 OK");
                    }
                    else if (resposta.ToString().StartsWith("TASK_COMPLETE"))
                    {
                        // Extrai o ID da tarefa concluída
                        string idTarefaConcluida = resposta.ToString().Substring("TASK_COMPLETE".Length).Trim();
                        // Atualiza o arquivo CSV correspondente
                        AtualizarTarefaConcluida("Servico_A.csv", idTarefaConcluida);
                        // Responde com confirmação de conclusão da tarefa
                        byte[] msg = Encoding.ASCII.GetBytes("TASK_COMPLETED");
                        stream.Write(msg, 0, msg.Length);
                        Console.WriteLine("Resposta enviada: TASK_COMPLETED");
                    }
                    else if (resposta.ToString() == "REQUEST_TASK")
                    {
                        // Lógica para atribuir uma nova tarefa ao cliente e atualizar o arquivo CSV
                        // Aqui você pode chamar o método AlocarNovaTarefa() para atribuir a nova tarefa
                    }
                    else if (resposta.ToString() == "QUIT")
                    {
                        // Responde com encerramento da conexão
                        byte[] msg = Encoding.ASCII.GetBytes("400 BYE");
                        stream.Write(msg, 0, msg.Length);
                        Console.WriteLine("Resposta enviada: 400 BYE");

                        // Fecha a conexão
                        cliente.Close();
                        break;
                    }
                    else
                    {
                        // Responde com erro
                        byte[] msg = Encoding.ASCII.GetBytes("ERROR");
                        stream.Write(msg, 0, msg.Length);
                        Console.WriteLine("Resposta enviada: ERROR");
                    }

                    // Limpa o StringBuilder para a próxima mensagem
                    resposta.Clear();
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Erro: " + ex.Message);
        }
        finally
        {
            // Encerra o servidor
            servidor.Stop();
        }
    }
}

 

classe cliente: 

 

using System;
using System.Net.Sockets;
using System.Text;

class Cliente
{
    static void Main(string[] args)
    {
        try
        {
            // Endereço IP e porta do servidor
            string servidorIp = "127.0.0.1";
            int porta = 8888;

            // Cria uma instância do cliente TCP
            TcpClient cliente = new TcpClient(servidorIp, porta);
            Console.WriteLine("Conectado ao servidor...");

            // Prepara as streams de rede
            NetworkStream stream = cliente.GetStream();
            byte[] dados = new byte[256];
            string resposta = string.Empty;

            Console.WriteLine("Indique o seu ID de Cliente: ");
            string idCliente = Console.ReadLine();

            // Envia mensagem de conexão
            string mensagemConnect = "CONNECT";
            byte[] msgConnect = Encoding.ASCII.GetBytes(mensagemConnect);
            stream.Write(msgConnect, 0, msgConnect.Length);
            Console.WriteLine("Mensagem enviada: {0}", mensagemConnect);

            // Lê a resposta do servidor
            int bytesConnect = stream.Read(dados, 0, dados.Length);
            resposta = Encoding.ASCII.GetString(dados, 0, bytesConnect);
            Console.WriteLine("Resposta recebida: {0}", resposta);

            while (true)
            {
                Console.WriteLine("Escolha uma opção:");
                Console.WriteLine("1. Concluir tarefa");
                Console.WriteLine("2. Solicitar nova tarefa");
                Console.WriteLine("3. Sair");
                Console.Write("Opção: ");
                string opcao = Console.ReadLine();

                switch (opcao)
                {
                    case "1":
                        // Envia mensagem de conclusão de tarefa
                        Console.WriteLine("Indique o ID da tarefa concluída: ");
                        string idTarefaConcluida = Console.ReadLine();
                        string mensagemConclusao = $"TASK_COMPLETE <{idTarefaConcluida}>";
                        byte[] msgConclusao = Encoding.ASCII.GetBytes(mensagemConclusao);
                        stream.Write(msgConclusao, 0, msgConclusao.Length);
                        Console.WriteLine("Mensagem enviada: {0}", mensagemConclusao);

                        // Lê a resposta do servidor
                        int bytesConclusao = stream.Read(dados, 0, dados.Length);
                        resposta = Encoding.ASCII.GetString(dados, 0, bytesConclusao);
                        Console.WriteLine("Resposta recebida: {0}", resposta);
                        break;

                    case "2":
                        // Envia pedido de nova tarefa
                        string mensagemPedido = "REQUEST_TASK";
                        byte[] msgPedido = Encoding.ASCII.GetBytes(mensagemPedido);
                        stream.Write(msgPedido, 0, msgPedido.Length);
                        Console.WriteLine("Mensagem enviada: {0}", mensagemPedido);

                        // Lê a resposta do servidor
                        int bytesPedido = stream.Read(dados, 0, dados.Length);
                        resposta = Encoding.ASCII.GetString(dados, 0, bytesPedido);
                        Console.WriteLine("Resposta recebida: {0}", resposta);
                        break;

                    case "3":
                        // Envia mensagem de encerramento
                        string mensagemQuit = "QUIT";
                        byte[] msgQuit = Encoding.ASCII.GetBytes(mensagemQuit);
                        stream.Write(msgQuit, 0, msgQuit.Length);
                        Console.WriteLine("Mensagem enviada: {0}", mensagemQuit);

                        // Lê a resposta do servidor
                        int bytesQuit = stream.Read(dados, 0, dados.Length);
                        resposta = Encoding.ASCII.GetString(dados, 0, bytesQuit);
                        Console.WriteLine("Resposta recebida: {0}", resposta);

                        // Fecha a conexão e sai do loop
                        cliente.Close();
                        return;

                    default:
                        Console.WriteLine("Opção inválida.");
                        break;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Erro: " + ex.Message);
        }
    }
}

O problema é que quando quero declarar uma tarefa concluída usando minha função UpdateCompletedTask, o arquivo csv não muda e permanece sempre o mesmo. Alguém pode me ajudar?

Alterei o código da minha função algumas vezes porque acho que o problema está na função UpdateCompletedTask mas ainda assim nada mudou.

 

Link to comment
Share on other sites

Tens aí vários problemas com o modo como lês e alteras o ficheiro.

Devias criar uma classe Tarefa que tenha todos os campos necessários.

Em seguida usas uma classe Tarefas que tenha um array/lista das Tarefas existentes e que tenha as funções de criar, alterar ou eliminar Tarefas. Esta classe vai tratar também da leitura e escrita do ficheiro CSV, assim tens controlo total sobre o ficheiro que é usado.

Na questão da leitura do ficheiro, deves fazer Split de cada linha pelo caracter que é utilizado para indicar a separação de colunas (normalmente , ou ; ) e carregar um objecto do tipo Tarefa para cada linha. Um problema dos CSV é que podes ter o caracter de separação de colunas no meio de outro texto e isso causa problemas, por isso tens sempre de ignorar todos os carateres que estejam entre ".

 

Se implementares isto vais deixar de usar o StartsWith (pode dar problemas se por algum motivo a lista não estiver ordenada) e o Replace do estado.

O campo Estado sugiro que troques o texto por um Integer (ou mesmo um Enum), é menos informação a guardar e é mais fácil gerir dentro da classe. Depois quando precisares de mostrar o texto do estado trocas nessa altura.

 

Chegando à tua questão, o problema pode estar no StartsWith se a coluna for do tipo Texto porque por vezes tem ' no início, ou outra situação do género, mas o melhor para perceberes isso será usar a opção de Debug (Depuração) que deves ter no Compilador para que pare nessa linha e possas acompanhar o que o código efetivamente faz.

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
×
×
  • 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.