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(); }