I have a device that acts as a TcpClient and sends TCP packets to a set IP on my network.
When I run the standard TcpListener program (from the official documentation), it gets stuck in the server.AcceptTcpClient()
instruction, never being able to actually detect the connection.
I have used Wireshark to check if the packets were actually being sent, and they are.
I have checked that packets are TCP and that the SYN is being sent. They are marked as duplicate ports since they are never accepted by the host.
This is my code (copied and slightly modified from the MS documentation above).
public static class Connection
{
public static void Connect(int port)
{
TcpListener server = null;
try
{
IPAddress localAddress = IPAddress.Parse("127.0.0.1");
server = new(localAddress, port);
// Start listening for clients
server.Start();
// Listening loop
while (true)
{
Console.WriteLine("Waiting for connection...");
// Wait for client to connect
TcpClient client = server.AcceptTcpClient(); // NEVER UNBLOCKS
// Close connection
client.Close();
}
}
catch (SocketException e)
{
Console.WriteLine("Socket exception: ", e);
}
finally
{
// Stop listening for clients
server.Stop();
}
}
}
To bind to the outgoing network adapter, rather than the loopback, use IPAddress.Any
server = new(IPAddress.Any, port);
You are also mising using
in various place, and ideally you should use async
. There also efficiencies you can make with reusing the same buffer.
public static async Task Connect(int port)
{
TcpListener server = null;
try
{
server = new(IPAddress.Any, port);
// Empezar a escuchar peticiones de clientes
server.Start();
// Buffer para leer datos
Byte[] buffer = new Byte[256];
string data = "";
// Entrar al bucle de escucha
while (true)
{
Console.WriteLine("Esperando conexión...");
// Bloquear el programa hasta aceptar una petición
using TcpClient client = await server.AcceptTcpClientAsync();
Console.WriteLine("Conectado!");
data = "";
// Crear una trama para leer y escribir
using NetworkStream stream = client.GetStream();
int i;
// Recibir todos los datos del cliente
while ((i = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)
{
data = System.Text.Encoding.ASCII.GetString(buffer, 0, i);
Console.WriteLine($"Recibido: {data}");
// Procesar los datos enviados por el cliente
data = data.ToUpper();
i = System.Text.Encoding.ASCII.GetBytes(data, 0, data.Length, buffer, 0);
// Enviar una respuesta
await stream.WriteAsync(buffer, 0, i);
Console.WriteLine($"Devuelto: {data}");
}
// Terminar la conexión
}
}
catch (SocketException e)
{
Console.WriteLine("Socket exception: ", e);
}
finally
{
// Dejar de escuchar clientes
if(server?.Active)
server.Stop();
}
}
Note that the above code will only deal with one client at a time. If you want to deal with multiple, you need to hand off the TcpClient
to a Task.Run
task.