![]() |
Neste artigo vamos criar uma aplicação para compartilhar arquivos usando a arquitetura cliente/servidor e os recursos dos sockets na linguagem C#. |
Lembrando que o exemplo funciona para arquivos menores que 1 GB e que para testar em máquinas remotas você deve verificar a comunicação entre as máquinas e as configurações do seu firewall.
Então vamos ao trabalho...
Criando o projeto no VS Community 2015
Abra no VS community 2015 e no menu File clique em New Project;
A seguir selecione o template Visual C# -> Windows -> Windows Forms Application e informe o nome TCPServidor e clique em OK;
Agora abra o formulário Form1.cs e inclua os seguintes controles no formulário:
3 Labels
2 TextBox - txtEnderecoIP, txtPorta
1 Buttons - btnEstabelecerConexao
Disponha os controles conforme o leiaute da figura abaixo:
Definindo o código do formulário
Inclua os seguintes namespaces no formulário:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
No início do formulário vamos declarar um delegate e um evento:
public delegate
void FileRecievedEventHandler(object fonte, string
nomeArquivo);
public event FileRecievedEventHandler
NovoArquivoRecebido;
No evento Load do formulário inclua o código abaixo estamos definindo o tratamento do evento definido:
private void Form1_Load(object sender, EventArgs e)
{
this.NovoArquivoRecebido += new FileRecievedEventHandler(Form1_NovoArquivoRecebido);
}
|
A seguir temos o código que define o evento definido :
private void Form1_NovoArquivoRecebido(object fonte, string nomeArquivo)
{
this.BeginInvoke(
new Action(
delegate ()
{
MessageBox.Show("Novo Arquivo recebido\n" + nomeArquivo);
System.Diagnostics.Process.Start("explorer", @"c:\");
}));
}
|
No evento Click do botão de comando Estabelecer Conexão inclua o código abaixo:
private void btnEstabelecerConexao_Click(object sender, EventArgs e)
{
int porta = int.Parse(txtPorta.Text);
string endIP = txtEnderecoIP.Text;
try
{
Task.Factory.StartNew(() => TratamentoArquivoRecebido(porta, endIP));
MessageBox.Show("Escutando na porta...: " + porta);
}
catch(Exception ex)
{
MessageBox.Show("Erro : " + ex.Message);
}
}
|
Neste código obtemos os valores para o IP e porta e chamamos o método TratamentoArquivoRecebido() passando essas informações para fazer o tratamento do arquivo que estamos recebendo.
O código do método TratamentoArquivoRecebido() é o seguinte:
public void TratamentoArquivoRecebido(int porta, string enderecoIp)
{
try
{
IPAddress ip = IPAddress.Parse(enderecoIp);
TcpListener tcpListener = new TcpListener(ip, porta);
tcpListener.Start();
while (true)
{
Socket manipularSocket = tcpListener.AcceptSocket();
if (manipularSocket.Connected)
{
string nomeArquivo = string.Empty;
NetworkStream networkStream = new NetworkStream(manipularSocket);
int thisRead = 0;
int blockSize = 1024;
Byte[] dataByte = new Byte[blockSize];
lock (this)
{
string caminhoPastaDestino = @"c:\dados";
manipularSocket.Receive(dataByte);
int tamanhoNomeArquivo = BitConverter.ToInt32(dataByte, 0);
nomeArquivo = Encoding.ASCII.GetString(dataByte, 4, tamanhoNomeArquivo);
//
Stream fileStream = File.OpenWrite(caminhoPastaDestino + nomeArquivo);
fileStream.Write(dataByte, 4 + tamanhoNomeArquivo, (1024 - (4 + tamanhoNomeArquivo)));
while (true)
{
thisRead = networkStream.Read(dataByte, 0, blockSize);
fileStream.Write(dataByte, 0, thisRead);
if (thisRead == 0)
break;
}
//
fileStream.Close();
}
NovoArquivoRecebido?.Invoke(this, nomeArquivo);
manipularSocket = null;
}
}
}
catch
{
throw;
}
}
|
No código acima temos o código que vai fazer o tratamento do arquivo que esta sendo recebido na porta e no endereço de ip informados.
Na nossa
aplicação do Servidor de compartilhamento de arquivos, é fornecido um número de
porta, no qual o servidor estará escutando, o endereço ip de origem e um arquivo
a ser recebido.
O botão Estabelecer Conexão inicia a escuta na porta indicada quando
clicado, invoca o método TratamentoArquivoRecebido em paralelo. Um objeto
TcpListener é criado para iniciar a escuta para o arquivo de entrada na
porta especificada, quando uma conexão é recebida um arquivo com o mesmo nome
que é o arquivo enviado do cliente é reconstruído a partir dos bytes recebidos e
salvo na unidade C:\dados e então um Evento é disparado para indicar na
interface do usuário do servidor que um novo arquivo foi recebido.
Quando o evento é disparado, todos os assinantes do evento são notificados e,
nesse caso, o método de manipulador de eventos Form1_NovoArquivoRecebido
é chamado e o código para exibir uma caixa de mensagem e abrir a pasta que
contém o arquivo recebido é envolvido em torno do método BeginInvoke para
evitar erros na thread.
Simples assim...
Lembrando que esse exemplo é uma das muitas
abordagens que podemos fazer para enviar arquivos.
No projeto eu criei uma classe chamada Servidor com o código abaixo onde temos o método Receber que mostra outra forma de receber o arquivo:(Fique a vontade para usar ou não esse método)
using System;
using System.Net.Sockets;
using System.Threading;
namespace TCPServidor
{
public class Servidor
{
public static void Receber(Socket socket, byte[] buffer, int offset, int tamanho, int timeout)
{
int startTickCount = Environment.TickCount;
int recebidos = 0; // quantos bytes foram recebidos
do
{
if (Environment.TickCount > startTickCount + timeout)
throw new Exception("Tempo esgotado...");
try
{
recebidos += socket.Receive(buffer, offset + recebidos, tamanho - recebidos, SocketFlags.None);
}
catch (SocketException ex)
{
if (ex.SocketErrorCode == SocketError.WouldBlock ||
ex.SocketErrorCode == SocketError.IOPending ||
ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
{
// o buffer do socket esta vazio , aguarde e tente novamente
Thread.Sleep(30);
}
else
throw ex; //ocorreu um erro
}
} while (recebidos < tamanho);
}
}
}
|
A seguir temos um trecho de código de como usar o método Receber :
Socket socket = tcpClient.Client;
byte[] buffer = new
byte[10]; // tamanho do texto "Alo
mundo!"
try
{
// recebe dados com timeout igual a 10s
Servidor.Receive(socket, buffer, 0, buffer.Length, 10000);
string arquivo = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
}
catch (Exception ex) { /*
... */ }
E assim temos a nossa aplicação TCPServidor pronta para receber arquivos.
Pegue o projeto completo aqui:
TCPServidor.zip
(Disse Jesus) Na verdade, na verdade vos digo que aquele que crê em mim tem a vida eterna. João 6:47
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Gostou ?
Compartilhe no Facebook
Compartilhe no Twitter
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
VB .NET - Programação MultiThread Socket - Servidor - Macoratti