I have a Signalr web app that is using sockets to interact with a server application I can't control (nore have a source code / a protocol for). Each Signalr client sends a command to a Signalr Hub which sends opens a socket, sends a command to the server app then gets one or more responses back, which get sent back to the signalr client.
What I'm finding is that periodically (not clear on why) the server app stops sending responses back to the Signalr Hub. It does this when deployed and also when debugging locally. I'm creating a new Socket connection for each client command and closing it once we've received everything from the server app.
Stopping and starting the web app always fixes this, however given I'm not reusing socket connections I'm really not sure what's making this fix work. My thinking is that if I can understand that I can fix the cause.
public async Task SendCommand(string device, string? command)
{
var ipendPoint = new IPEndPoint(ipaddress, port);
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
ReceiveTimeout = (int)TimeSpan.FromSeconds(5).TotalMilliseconds,
SendTimeout = (int)TimeSpan.FromSeconds(30).TotalMilliseconds,
};
await socket.ConnectAsync(ipendPoint);
try
{
while (true)
{
string? response = await SendCommandToServerAsync(socket, ipendPoint, device, command);
command = null;
if (response == null)
{
await Task.Delay(2000);
continue;
}
if (response.Trim() != "GET&")
{ // If we're only sent a 'get' then don't update the client since there's no prompt
var parsedResponse = ParseResponse(response);
await Clients.Group(device).SendAsync("ReceiveResponse", device, parsedResponse);
}
if (response.Trim().EndsWith("GET&"))
{
break;
}
await Task.Delay(2000);
}
}
finally
{
if (socket.Connected)
{
socket.Close();
}
}
}
private async Task<string?> SendCommandToServerAsync(Socket socket, IPEndPoint ipendPoint, string device, string? command)
{
var responseSB = new StringBuilder();
var debugSB = new StringBuilder();
var text = device + "&" + command?.ToUpper() + "\r\n";
var bRequest = Encoding.UTF8.GetBytes(text.ToString());
debugSB.Append("request: " + text);
string? result;
try
{
if (command != null)
{
debugSB.AppendLine("Sent request");
await socket.SendAsync(bRequest);
}
else
{
debugSB.AppendLine("Command is null");
}
await Task.Delay(900);
byte[] array = new byte[8192];
int num2 = 0;
string text2;
while (true)
{
await Task.Delay(300);
if (!socket.Connected)
{
debugSB.AppendLine("Socket not connected");
socket.Connect(ipendPoint);
}
int num3 = await socket.ReceiveAsync(array, SocketFlags.None);
debugSB.AppendLine("Received " + num3.ToString() + " bytes");
num2++;
if (num3 > 0)
{
text2 = Encoding.Default.GetString(array, 0, num3);
responseSB.AppendLine("Received: " + text2);
string text3 = text2;
text3 = text3.Replace("BEEP&" + '�', "");
if (!(text3 == "") && text2.IndexOf('�') >= 0)
{
break;
}
else
{
_emailSender.SendEmail("[email protected]", "AquaBar Info", "Got here with response: " + text2);
}
}
else if (num2 == 20)
{
debugSB.AppendLine("Going to block_12");
goto Block_12;
}
}
debugSB.AppendLine("Out of while loop");
string[] array2 = text2.Split(['�']);
if (array2.Length > 2 && array2[0] == array2[1] && array2[0] != "BEEP&" && array2[0] != "PROMPT&")
{
text2 = array2[1];
}
return text2.Replace('�', ' ');
Block_12:
result = "Please Enter to Continue..GET&";
_emailSender.SendEmail("[email protected]", "AquaBar Info", "Got to Please enter with response: " + responseSB.ToString() + Environment.NewLine + Environment.NewLine + "Debug: " + Environment.NewLine + debugSB.ToString());
}
catch (SocketException ex) when (ex.SocketErrorCode == SocketError.TimedOut)
{
result = null;
}
catch (IOException)
{
result = null;
}
catch (Exception)
{
result = "BEEP& ***Error***\n Server connection error.\n Please contact Administrator.";
}
return result;
}
Task.Delay
?