I have a TCP listener application written in .NET 8 which is supposed to listen for incoming client connection, accept connection and process the the massage that comes in and responds to the client.
Locally when I run the TCP listener and client, I am able to send message from the client to the listener and the listener responds fast as it should.
Below is the code for the listener, Please note the listener processes an ISO8583 message
public class TcpServerHostedService : BackgroundService{ IPAddress _ipAddress = IPAddress.Parse("127.0.0.1"); int _port = 2000; private readonly IServiceProvider _serviceProvider; private readonly IConfiguration _configuration; private readonly ILogger<TcpServerHostedService> _logger; public TcpServerHostedService(IServiceProvider serviceProvider, IConfiguration configuration, ILogger<TcpServerHostedService> logger) { _serviceProvider = serviceProvider; _configuration = configuration; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { TcpListener listener = new TcpListener(_ipAddress, _port); listener.Start(); Console.WriteLine("EchoServer started..."); while (!stoppingToken.IsCancellationRequested) { Console.WriteLine("Waiting for incoming client connections..."); TcpClient client = await listener.AcceptTcpClientAsync(); Console.WriteLine("Accepted new client connection..."); NetworkStream stream = client.GetStream(); try { using (var scope = _serviceProvider.CreateScope()) { var _transactionService = scope.ServiceProvider.GetRequiredService<IAfslTransactionService>(); var _mailService = scope.ServiceProvider.GetRequiredService<IMailService>(); while (!stoppingToken.IsCancellationRequested) { // Read the header bytes byte[] headerBytes = new byte[2]; stream.Read(headerBytes, 0, 2); // Calculate the message length based on the header bytes int messageLength = headerBytes[0] * 256 + headerBytes[1]; // Receive data from the client byte[] receiveBuffer = new byte[messageLength]; int bytesRead = await stream.ReadAsync(receiveBuffer, 0, receiveBuffer.Length); // Convert received bytes to string string receivedData = Encoding.UTF8.GetString(receiveBuffer, 0, bytesRead); // Process the ISO 8583 message string response = await ProcessIsoMessage(receivedData, _transactionService, _mailService); // Convert string message to bytes using UTF-8 encoding string message = response; byte[] messageBytes = Encoding.UTF8.GetBytes(message); // Get the length of the message and convert it to bytes (using 2 bytes for simplicity) byte[] resheaderBytes = BitConverter.GetBytes((short)messageBytes.Length); // Ensure the bytes are in network byte order (big endian) if (BitConverter.IsLittleEndian) { Array.Reverse(resheaderBytes); } // Send the length header bytes to the stream await stream.WriteAsync(resheaderBytes, 0, resheaderBytes.Length); // Send the actual message bytes to the stream await stream.WriteAsync(messageBytes, 0, messageBytes.Length); await stream.FlushAsync(); } } } catch (Exception ex) { _logger.LogError(ex, "An error occurred on TCP"); } } } private async Task<string> ProcessIsoMessage(string isoMessage, IAfslTransactionService _transactionService, IMailService _mailService) { MessageParser.NET.Tools.ISO8583 iso = new MessageParser.NET.Tools.ISO8583(); string[] data = iso.Parse(isoMessage); Dictionary<int, string> isoFields = ParseStringArrayToDictionary(data); string messageTypeCode = isoFields.ContainsKey(0) ? isoFields[0] : ""; if (!string.IsNullOrEmpty(messageTypeCode)) { Dictionary<int, string> result = new Dictionary<int, string>(); switch (messageTypeCode) { case "0100": result = await _transactionService.ProcessHoldReleaseFunds(isoFields); break; case "0200": result = await _transactionService.ProcessFinancialTransaction(isoFields); break; case "0420": result = await _transactionService.ProcessReversal(isoFields); break; case "0800": result = await _transactionService.ProcessNetworkManagement(isoFields); break; } //Message Type Identifier (Financial Message Response) string MTI = result[0]; //1. Create Arrays AND Assign corresponding data to each array string[] DE = ParseDictionaryToStringArray(result); //3.Use "Build" method of object iso8583 to create a new message. string NewISOmsg = iso.Build(DE, MTI); // Send ISO MESSAGE return NewISOmsg; } return string.Empty; } static Dictionary<int, string> ParseStringArrayToDictionary(string[] array) { Dictionary<int, string> dictionary = new Dictionary<int, string>(); for (int i = 0; i < array.Length; i++) { // Extract key and value from the item int key = i; // Assuming keys are single digits string value = array[i]; // Check if key is "129", assign it to key "0" in dictionary if (key == 129) { dictionary[0] = value; } // Check if key is "0" or "1", merge them and assign to key "1" in dictionary else if (key == 0 || key == 1) { if (dictionary.ContainsKey(1)) { dictionary[1] += value; } else { dictionary[1] = value; } } // Check if the value is not "null" else if (value != null) { dictionary[key] = value; } } return dictionary; } static string[] ParseDictionaryToStringArray(Dictionary<int, string> dictionary) { dictionary.Remove(0); dictionary.Remove(1); string[] DE = new string[130]; for (int i = 0; i < DE.Length; i++) { string value; dictionary.TryGetValue(i, out value); DE[i] = !string.IsNullOrEmpty(value) ? value : null; } return DE; }}
The problem I am facing here is that when I deploy the listener on an ubuntu server I send a message from the TCP Client to the listener and it takes time to respond sometimes even up to 3-5 minutes and this is not good.
Just to mention, I have an Nginx server that handles incoming request for Stream and sends it to my application on the ubuntu server but I don't think the nginx is the problem because I tried binding the application port to the server port direction and I still got same issue of delayed response.
Please has anyone faced this type of challenge and what can I do to resolve this issue, because this doesn't look like a code issue