quarta-feira, outubro 20, 2010

Criando um web site - Sample WebSite Parte 1

A pouco tempo ministrei o curso 2310 - Developing Web Applications Using Microsoft Visual Studio 2008 e resolvi criar uma aplicação para mostrar um pouco mais da implementação na vida real.

Vou abordar essa aplicação em varias partes para não ficar muito extensa e focar mais no exemplo de cada artigo.

Banco de dados - inicialmente o banco vai conter três tabelas:
Usuario
Produto
UsuarioXProduto
A estrutura do projeto consiste em três camadas, Business Layer(Regras de Negocios), DBAccess(Acesso a Dados) e DB Model(Modelo do Banco).

Funcionamento:
DBModel - contém o modelo do banco de dados
Business Layer - contém todas as regras de negócios da aplicação
DBAccess - contém os métodos de acesso a dados

sexta-feira, outubro 01, 2010

TCP Client & Server

Essa semana precisei fazer um server e um client usando TCP. Depois de muita busca achei a melhor solução no livro C# CookBook 2nd Edition da Editora O´Reilly. Mas claro que no livro a solução não estava 100%, faltava declarar uns namespaces e um objeto.

No livro o autor cita que será usado o System.Net mas assim que comecei a ler o codigo percebi que ia precisar de outras namespaces, então declarei as seguintes:

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

No meu caso utilizei as listadas a cima mas para seguir o exemplo do livro também é necessário declarar a seguinte namespace para utilizar o Trace:

using System.Diagnostics;

Com isso fiz a seguinte alteração no codigo, troquei o Trace.WriteLine por Console.WriteLine, assim consigo ver todos os resultados no console, quando o Trace aparece apenas no output do debug.

Como a classe é meio grande vou fatiar em pedaços para ficar mais claro mas fica o link para baixar o codigo.

A estrutura inicial da classe é a seguinte:

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

namespace TCP_UDP_Server
{
    public class TCPServer
    {
        private TcpListener listener = null;
        private IPAddress address;
        private int port;
        private bool listening = false;
        private object _syncRoot;

        public TCPServer(IPAddress address, int port)
        {
            this.address = address;
            this.port = port;
            _syncRoot = this;
        }

        public void Listen()
        {
            //CODE HERE
        }

        public void StopListening()
        {
            if (listening)
            {
                lock (_syncRoot)
                {
                    listening = false;
                    listener.Stop();
                }
            }
        }

        private void ProcessClient(object client)
        {
            //CODE HERE
        }

        public IPAddress Address
        {
            get { return address; }
        }

        public int Port
        {
            get { return port; }
        }

        public bool Listening
        {
            get { return listening; }
        }
    }
}

No método Listen() é criado uma escuta para o endereço e a porta configurada. Após isso fica escutando a porta por mensagens do client(o client não vou comentar nesse post, vou criar outro só para explicar sua funcionalidade).

try
{
    lock (_syncRoot)
    {
        listener = new TcpListener(address, port);
        listener.Start();
        listening = true;
    }

    do
    {
        Console.Write("Looking for someone to talk to... ");

        TcpClient newClient = listener.AcceptTcpClient();
        Console.Write("Connected to new client");

        ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessClient), newClient);

    } while (listening);
}
catch (SocketException se)
{
    Console.WriteLine("SocketException: ", se.ToString());
}
finally
{
    StopListening();
}

E no método ProcessClient() é recebido o pacote e transformado em uma string. Ao receber os dados retorna uma mensagem para o client avisando o recebimento.

TcpClient newClient = (TcpClient)client;
try
{
    byte[] bytes = new byte[1024];
    StringBuilder clientData = new StringBuilder();

    using (NetworkStream ns = newClient.GetStream())
    {
        ns.ReadTimeout = 60000;
        int bytesRead = 0;
        do
        {
            try
            {
                bytesRead = ns.Read(bytes, 0, bytes.Length);
                if (bytesRead > 0)
                {
                    clientData.Append(Encoding.ASCII.GetString(bytes, 0, bytesRead));
                    ns.ReadTimeout = 3000;
                }
            }
            catch (IOException ioe)
            {
                Console.WriteLine("Read time out: "+ ioe.Message);
                bytesRead = 0;
            }
        } while (bytesRead > 0);

        Console.WriteLine("Client says: " + clientData.ToString());

        bytes = Encoding.ASCII.GetBytes("Thanks call again!");

        ns.Write(bytes, 0, bytes.Length);
    }
}
finally 
{
    if (newClient != null)
        newClient.Close();
}