I created a simple C# console application (net7.0) as a server for my multiplayer card game. It uses HttpListener to receive connection requests, then upgrades to a websocket connection.
// Start listening for websocket requests
public async void Start()
{
HttpListener listener = new();
listener.Prefixes.Add("http://+:80/cardgame/");
listener.Start();
#if DEBUG
Console.WriteLine("Listening...");
#endif
while (true)
{
HttpListenerContext listenerContext = await listener.GetContextAsync();
if (listenerContext.Request.IsWebSocketRequest)
{
ProcessRequest(listenerContext);
}
else
{
listenerContext.Response.StatusCode = 400;
listenerContext.Response.Close();
}
}
}
This works on my windows laptop, when running the app as admin or using the netsh add urlacl url=http://+:80/cardgame user=DOMAIN\user
in CMD beforehand.
I want to host this in Azure Cloud as a Webapp using the 'Free' settings. Deployment was successful, but when starting the webapp it throws an access denied exception because of the HttpListener. The exact scenario: Image
Unhandled exception. System.Net.HttpListenerException (5): Access is denied.
at System.Net.HttpListener.SetupV2Config()
at System.Net.HttpListener.Start()
I also tried it with listener.Prefixes.Add("http://+:80/");
and with the public IP of the webapp at the place of the '+' sign, but to no avail.
Azure Kudu environment doesn't run the app in admin mode, but it also doesn't allow the netsh
command to be configured, so I'm stating to feel like this is not possible to do... But then what is this webapp environment good for if you can't even listen to a port? (for ASP.NET I suppose...)
I would really appreciate if anybody could help me out with this:
No, it is not possible to configure a WebSocket connection on Azure Web App environment using a C# console application.
We can deploy an ASP.NET, ASP.NET Core Web API, ASP.NET Core Blazor, and ASP.NET MVC web app to Azure App Service.
Use Azure Web PubSub Service and Azure SignalR as WebSockets in Azure.
The following code creates a WebSocket connection and allows the user to send and receive messages.
Using Azure Web PubSub Service in Blazor:
@page "/websocket"
<h1>Echo test</h1>
<h3>State: @webSocket.State</h3>
@if(webSocket.State == WebSocketState.Open) {
<form @onsubmit="SendMessageAsync">
Message: <input @bind="@message" />
<button type="submit">Send</button>
</form>
<pre>@log</pre>
}
@code {
private CancellationTokenSource disposalTokenSource = new CancellationTokenSource();
private ClientWebSocket webSocket = new ClientWebSocket();
private string message = "Hello, websocket!";
private string log = "";
protected override async Task OnInitializedAsync() {
await ConnectWebSocketAsync();
_ = ReceiveLoop();
}
private async Task ConnectWebSocketAsync() {
// Update the URI with your actual WebSocket endpoint and access token
var uri = new Uri("wss://your-websocket-endpoint?access_token=your-access-token");
await webSocket.ConnectAsync(uri, disposalTokenSource.Token);
}
private async Task SendMessageAsync() {
log += $"Sending: {message}\n";
var dataToSend = new ArraySegment<byte>(Encoding.UTF8.GetBytes(message));
await webSocket.SendAsync(dataToSend, WebSocketMessageType.Text, true, disposalTokenSource.Token);
}
private async Task ReceiveLoop() {
var buffer = new ArraySegment<byte>(new byte[1024]);
while(!disposalTokenSource.Token.IsCancellationRequested) {
var received = await webSocket.ReceiveAsync(buffer, disposalTokenSource.Token);
if (received.MessageType == WebSocketMessageType.Text) {
var receivedAsText = Encoding.UTF8.GetString(buffer.Array, 0, received.Count);
log += $"Received: {receivedAsText}\n";
StateHasChanged();
}
}
}
public void Dispose() {
disposalTokenSource.Cancel();
_ = webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Bye", CancellationToken.None);
}
}
Local:
Azure:
For Azure SignalR with Blazor :
I followed the reference for the configuration of Azure SignalR in Blazor
dotnet add package Microsoft.Azure.SignalR
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddServerSideBlazor();
services.AddSignalR().AddAzureSignalR();
...
}
appsetting.json:
"Azure": {
"SignalR": {
"Enabled": true,
"ConnectionString": <your-connection-string>
}
}
Local:
Azure: