I am running a Node by Bitnami server running Apache on AWS. I am trying to run an Asp.Net backend, and have run into no shortage of problems. I am getting the following error whenever I try to run my program:
System.IO.IOException: Failed to bind to address https://[::]:49156: address already
in use.
It does not matter what the address is set to, this occurs for every address. Sometimes it works, but then when I restart the program with the same address, it gives the same error again.
How can every address possibly be in use?
When I check the ports, nothing shows up, even when using sudo, so there's nothing using the ports.
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(kestrel =>
{
kestrel.ListenAnyIP(49155, portOptions =>
{
portOptions.UseHttps(h =>
{
h.UseLettuceEncrypt(kestrel.ApplicationServices);
});
});
});
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddLettuceEncrypt();
// Add CORS policy
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowAll",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
// Use CORS policy
app.UseCors("AllowAll");
app.UseAuthorization();
app.UsePathBase("/api");
app.MapControllers();
app.Run();
Here is what my Program.cs looks like
ASP.Net is primarily designed with Windows in mind. On Windows, when you quit a server process and start a new one, the new process can immediately bind to the port previously used by the old process.
On Linux, the situation is different. By default, once a bound “server” socket is closed (e.g. when a process exits), the port is reserved by the kernel for a period of time - technically, the port enters a TIME_WAIT
state during which it cannot be bound to. You can read this ServerFault answer for more details on why this behaviour exists.
The usual workaround in Linux is to specify SO_REUSEADDR
when binding the socket, allowing a second process to immediately bind to the same port. Many server libraries designed for Linux expose this option as it is commonly needed, particularly when developing a new server. Note that Windows has this option too, but its only use is to allow two servers to bind the same port at the same time - which is rarely useful.
For ASP.Net and the Kestrel web server, you can set the SO_REUSEADDR
option manually as follows (note: untested as I typed this out on my phone without a working ASP.Net setup):
var builder = WebApplication.CreateBuilder(args);
// …
builder.WebHost.UseSockets(socketOptions => {
socketOptions.CreateBoundListenSocket = endpoint => {
ip = (IPEndPoint)endpoint;
Socket listenSocket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
if (ip.Address.Equals(IPAddress.IPv6Any))
{
listenSocket.DualMode = true;
}
listenSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
listenSocket.Bind(endpoint);
return listenSocket;
};
});