locked
C# Reading data on TCP truncated, not reading all the data RRS feed

  • Question

  • User-1379762086 posted

    Please i need help, i wrote a c# application that receives data over TCP, processes the data and return output message to the sender, some i noticed that the data i receives is not always complete and sometimes not in the same format send. Below is my code 

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading.Tasks;

    namespace ParkwayIso
    {
    public class Program
    {

    public static void Main(string[] args)
    {
    //ISOprocessing isoprs = new ISOprocessing();
    //isoprs.StartListening();
    // AsynchronousSocketListener aslint = new AsynchronousSocketListener();


    StartListening();

    }
    public static void StartListening()
    {
    // Data buffer for incoming data.
    byte[] bytes = new Byte[4096];
    byte[] returnArray = null;
    string data = String.Empty;
    string strReturn = null;
    string localIP;
    string localip = ConfigurationManager.AppSettings["localip"].ToString();
    string localportno = ConfigurationManager.AppSettings["localportno"].ToString();
    using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
    {

    socket.Connect(localip, Convert.ToInt32(localportno));
    IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
    localIP = endPoint.Address.ToString();
    }

    IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(localIP), Convert.ToInt32(localportno));
    Socket listener = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream,
    ProtocolType.Tcp);

    try
    {
    listener.Bind(localEndPoint);

    listener.Listen(300);

    // Start listening for connections.
    while (true)
    {
    Console.WriteLine("Waiting for a connection...");
    Socket handler = listener.Accept();
    data = null;

    while (true)
    {
    bytes = new byte[4096];
    returnArray = null;
    strReturn = null;
    data = null;


    // Get incoming connection's ip and port for logging purposes
    EndPoint endpoint = handler.RemoteEndPoint;
    IPEndPoint iPEndPoint = null;
    if (endpoint != null)
    {
    iPEndPoint = (IPEndPoint)endpoint;
    // logger.Information($"Incoming connection IP - {iPEndPoint.Address}:{iPEndPoint.Port}");
    }

    int bytesRec = handler.Receive(bytes);

    // try to parse if not break
    data += Encoding.ASCII.GetString(bytes, 0, bytesRec);

    if (string.IsNullOrWhiteSpace(data))
    {
    break;
    }

    Console.WriteLine("----------about to show raw data-------------");
    Console.WriteLine(data);

    // All the data has been read from the
    // client. Display it on the console.
    Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
    data.Length, data);
    // Echo the data back to the client.

    string reslt = String.Empty;
    data = data.ToString().Replace("< ", "<").Replace(" >", ">").Replace("</ ", "</");

    int indexOfstring = data.IndexOf("<Iso8583PostXml>");
    if (indexOfstring >= 1)
    {

    reslt = data.Substring(indexOfstring, data.Length - indexOfstring);

    }

    if (reslt.Contains("<Iso8583PostXml>") && reslt.Contains("</Iso8583PostXml>"))
    {

    Console.WriteLine("----------about to read iso message-------------");

    Console.WriteLine(reslt);

    ISOTranst iostran = new ISOTranst();

    //send to the method that will process the data and return response message
    string rntiso = iostran.ATMRequest(reslt);

    //rntiso is the response message

    Console.WriteLine("----------about to send iso messagee-------------");
    Console.WriteLine(rntiso);


    string remoteip = ((IPEndPoint)(handler.RemoteEndPoint)).Address.ToString();

    string locallip = ((IPEndPoint)(handler.LocalEndPoint)).Address.ToString();

    Console.WriteLine("local IP Address: " + locallip);

    Console.WriteLine("Remote IP Address: " + remoteip);

    int remoteport = ((IPEndPoint)(handler.RemoteEndPoint)).Port;

    Console.WriteLine("Remote port no : " + remoteport.ToString());


    // Parse the data,

    // Process the data, and generate a response.
    string toSend = String.Empty;
    toSend = rntiso;
    byte[] msg;
    using (MemoryStream stream = new MemoryStream())
    {
    msg = System.Text.Encoding.ASCII.GetBytes(toSend);
    byte firstByte = Convert.ToByte(msg.Length / 256);
    byte secondByte = Convert.ToByte(msg.Length % 256);

    byte[] dataLength = { firstByte, secondByte };
    stream.Write(dataLength, 0, dataLength.Length);
    stream.Write(msg, 0, msg.Length);
    returnArray = stream.ToArray();
    }

    msg = System.Text.Encoding.ASCII.GetBytes(toSend);
    strReturn = System.Text.Encoding.ASCII.GetString(returnArray);
    if (returnArray != null)
    {
    handler.Send(returnArray);
    }

    }//end <Iso8583PostXml>

    }

    }

    }
    catch (Exception e)
    {

    }

    }
    }
    }

    Tuesday, September 4, 2018 2:33 PM

Answers

  • User475983607 posted

    The posted code ignores exceptions.  The code assumes the receive buffer has the entire message on the first read. 

    It looks like you based your code on the synchronous socket programming docs but did not follow the pattern.  The docs shows the data read in a loop until all the data is  received.  Your code tries to parse the data as soon as data is available.  In TCP there is no guarantee the receive buffer has a complete message.

    https://docs.microsoft.com/en-us/dotnet/framework/network-programming/socket-code-examples

    I'm not sure what "same format" means as it looks like you're parsing a string.  I assume you are seeing effects if processing the second part of a message.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, September 4, 2018 3:10 PM