Closed vivekspraxa closed 4 years ago
What exactly are you executing here. I can see some Controller code and the server. Please provide either a working example or more details on how to reproduce it.
Here is the code for
MqttServer.cs `using Color.Controllers; using MQTTnet; using MQTTnet.Client; using MQTTnet.Protocol; using MQTTnet.Server; using Newtonsoft.Json; using NLog; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web;
///
private async static void CreateServer()
{
if (mqttServer == null)
{
var options = new MqttServerOptions
{
ConnectionValidator = c =>
{
c.ReturnCode = MqttConnectReturnCode.ConnectionAccepted;
}
};
mqttServer = new MqttFactory().CreateMqttServer();
mqttServer.ApplicationMessageReceived += (s, e) =>
{
switch (e.ApplicationMessage.Topic)
{
case "server":
string json = Encoding.UTF8.GetString(e.ApplicationMessage.Payload ?? new byte[0]);
WifiMessage wm = JsonConvert.DeserializeObject<WifiMessage>(json);
break;
case "ping":
string macAddress = e.ClientId;
break;
default:
logger.Debug(e.ClientId + " reported " + e.ApplicationMessage.Topic + "> " + Encoding.UTF8.GetString(e.ApplicationMessage.Payload ?? new byte[0]));
break;
}
};
mqttServer.ClientDisconnected += (s, e) =>
{
string macAddress = e.ClientId;
logger.Debug("Mqtt Disconnected " + e.ClientId);
};
mqttServer.ClientConnected += (s, e) =>
{
string macAddress = e.ClientId;
logger.Debug("Mqtt Connected " + e.ClientId);
};
mqttServer.Started += (s, e) => {
logger.Debug("Mqtt Server started");
};
try
{
await System.Threading.Tasks.Task.Run(() => mqttServer.StopAsync().GetAwaiter().GetResult());
await System.Threading.Tasks.Task.Run(() => mqttServer.StartAsync(options).GetAwaiter().GetResult());
}
catch (Exception ex)
{
logger.Debug(ex);
}
}
}
public static IMqttServer GetMqttServer()
{
if (mqttServer == null)
{
logger.Debug("Mqtt GetMqttServer ");
CreateServer();
}
return mqttServer;
}
public static void SendMessage(string macAddress, byte[] value, bool retain)
{
if (mqttServer == null)
{
logger.Debug("Mqtt SendMessage ");
CreateServer();
}
MqttApplicationMessage message = new MqttApplicationMessageBuilder()
.WithTopic(macAddress)
.WithPayload(value)
.WithExactlyOnceQoS()
.WithRetainFlag(retain)
.Build();
mqttServer.PublishAsync(message).GetAwaiter().GetResult();
}
}
}`
And Startup.cs ` using Microsoft.Owin; using Owin; using Color; using System; using NLog;
[assembly: OwinStartup(typeof(ColoR.Startup))] namespace ColoR { public class Startup { private static Logger logger = LogManager.GetLogger("Startup");
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
MQTTServer.GetMqttServer();
}
}
}`
I just looked up the socket binding code for server and it doesn't set "reuse address" socket option, which it should. Without that option, the port is still "in use" for a couple of minutes after the server has exited.
To the developer: before calling Bind
on the socket, you should use https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.setsocketoption?view=netcore-2.2#System_Net_Sockets_Socket_SetSocketOption_System_Net_Sockets_SocketOptionLevel_System_Net_Sockets_SocketOptionName_System_Boolean_ to set SocketOptionName.ReuseAddress
to true. (Use SocketOptionLevel.Socket
).
EDIT: I have just successfully created the server and connected the client multiple times within a minute w/o any problem. This is on Windows though.
Is this issue fixed in latest version ?
@vivekspraxa You can fix this by using new MqttServerOptionsBuilder().Build().TlsEndpointOptions.ReuseAddress = true;
or anything similar.
See also https://github.com/chkr1011/MQTTnet/issues/872#issuecomment-644053219.
I am using Startup.cs to start the mqtt server but sometimes getting this error , it will get removed by restating iis
2018-12-12 20:20:16.1372 MQTTServer System.Net.Sockets.SocketException (0x80004005): Only one usage of each socket address (protocol/network address/port) is normally permitted at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress) at System.Net.Sockets.Socket.Bind(EndPoint localEP) at MQTTnet.Implementations.MqttTcpServerListener.Start() at MQTTnet.Implementations.MqttTcpServerAdapter.RegisterListeners(MqttServerTcpEndpointBaseOptions options, X509Certificate2 tlsCertificate) at MQTTnet.Implementations.MqttTcpServerAdapter.StartAsync(IMqttServerOptions options) at MQTTnet.Server.MqttServer.<StartAsync>d__35.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Color.MQTTServer.CreateServer() in e:\Color\App_Code\Controllers\MQTTServer.cs:line 159 System.Net.Sockets.SocketException (0x80004005): Only one usage of each socket address (protocol/network address/port) is normally permitted at System.Net.Sockets.Socket.DoBind(EndPoint endPointSnapshot, SocketAddress socketAddress) at System.Net.Sockets.Socket.Bind(EndPoint localEP) at MQTTnet.Implementations.MqttTcpServerListener.Start() at MQTTnet.Implementations.MqttTcpServerAdapter.RegisterListeners(MqttServerTcpEndpointBaseOptions options, X509Certificate2 tlsCertificate) at MQTTnet.Implementations.MqttTcpServerAdapter.StartAsync(IMqttServerOptions options) at MQTTnet.Server.MqttServer.<StartAsync>d__35.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at Color.MQTTServer.CreateServer() in e:\Color\App_Code\Controllers\MQTTServer.cs:line 159