C # Networking: server freezes after receiving more than 65535 bytes

UPDATE: Due to issues with administrators here at Stackoverflow, I posted a very dull version of the same issue on the MSDN forum. This text below uses MyNetworking.dll, but this is not a problem. This is a very thin client-server thing, and the problem is exactly the same. Feel free to try =) http://social.msdn.microsoft.com/Forums/en-US/netfxnetcom/thread/d3d33eb9-7dce-4313-929e-a8a63d0f1e03 / UPDATE

So, I have a strange error.

Usually we have a DLL that processes our networks. Lets call it MyNetworking.dll. We use it everywhere on our servers and clients and have been doing this for 5 years. I have not had a problem with this, so far.

I have an "XMLPoller" that reads XML from a MySQL database, serializes it into a byte [] array, and sends it over the network. These specific XML messages are 627 bytes in serialized form.

XMLPoller connects to the port on the "remote server" (which is the local host) and sends packets one at a time. With the exact nbr 105 packet, the connection is closed. 104 packets are sent from XMLPoller and accepted by the server. 104 x 627 = 65208 bytes. But packet 105, when the total number of bytes sent will be 65835, the connection closes with this error:

System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
       at System.Net.Sockets.Socket.EndReceive(IAsyncResult asyncResult)
       at System.Net.Sockets.NetworkStream.EndRead(IAsyncResult asyncResult)

This is a server error. However, I went through the XMLPoller (client), and I see when the last 627 bytes are sent (thus sending up to 65835 bytes), and I see no errors on the client, it sends the send without problems.

20:15 UPDATE SWEDISH TIME

, :

Unable to read data from the transport connection: An established connection was aborted by the software in your host machine.

, , . , - , , .

/EndUpdate

, , . - -, . TCPInput; - ?

MyNetworking.dll.

Socket ( ), :

public void setConnected(Socket thisClient)
{
    NetworkStream stream = new NetworkStream(thisClient);
 socket = thisClient;
 output = new TCPOutput(stream, outputHandler,this);
 remoteIP = this.socket.RemoteEndPoint.ToString();
 changeState(State.Connected);
    try
    {
        stream.BeginRead(inputBuffer, 0, 5000, new AsyncCallback(OnDataReceived), null);
    }
    catch (Exception e)
    {
        this.disconnect();
    }
}

OnDataReceived ( ):

public void OnDataReceived(IAsyncResult asyn)
        {
            int nbrRead = 0;
            byte[] tmp = null;
            try
            {
                nbrRead = stream.EndRead(asyn);
                tmp = new byte[nbrRead];
            }
            catch (Exception e)
            {
                // *** HERE IS WHERE THE EXCEPTION IS CAUGHT ***
                System.Diagnostics.Debugger.Log(0, "Bla1", e.ToString());
                this.disconnect();
            }
            if (nbrRead > 0)
            {
                try
                {
                    Array.Copy(inputBuffer, 0, tmp, 0, nbrRead);
                }
                catch(Exception e)
                {
                    System.Diagnostics.Debugger.Log(0, "Bla2", e.ToString());
                    this.disconnect();
                }
                preProcessMessage(tmp);
                try
                {
                    stream.BeginRead(inputBuffer, 0, 5000, new AsyncCallback(OnDataReceived), new object());
                }
                catch(Exception e)
                {
                    System.Diagnostics.Debugger.Log(0, "Bla3", e.ToString());
                    this.disconnect();
                }
            }
            else
                this.disconnect();

        }

, ... ?

1:

:

public bool sendData(byte[] data)
        {
            if(this.state == State.Connected)
            {
                if (data != null && data.Length > 0)
                {
                    try
                    {
                        //data = Crypto.Encrypt("a1s2d3", data);
                        outputStream.Write(data, 0, data.Length);
                    }
                    catch(Exception e)
                    {
                        System.Diagnostics.Debug.WriteLine("ClientHandler.sendData> " + e.ToString());
                    }
                    //parent.outDataLog(data.Length);
                }
            }
            return true;
        }

2

Flush - :

public bool sendData(byte[] data)
{
    if(this.state == State.Connected)
    {
        if (data != null && data.Length > 0)
        {
            try
            {
                //data = Crypto.Encrypt("a1s2d3", data);
                outputStream.Write(data, 0, data.Length);
                outputStream.Flush();
            }
            catch(Exception e)
            {
                System.Diagnostics.Debug.WriteLine("ClientHandler.sendData> " + e.ToString());
            }
            //parent.outDataLog(data.Length);
        }
    }
    return true;
}

3:

, , . 5 , =)

ClientHandler.cs (, ..)

using System;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace tWorks.tNetworking.tNetworkingCF
{
    /// <summary>
    /// Summary description for connectionHandler.
    /// </summary>
    public class ClientHandler
    {
        #region Fields (17) 

        string address;
        Connector connector;
        DataHandler dataHandler;
        int id;
        TCPInput input;
        int interval;
        string localAddress;
        IPEndPoint localPoint;
        int localPort;
        NetworkStream outputStream;
        public TTCPClientInterface parent;
        int port;
        tWorks.tNetworking.Protocol.Protocol protocol;
        bool reconnect;
        string remoteIP;
        Socket socket;
        public State state;

        #endregion Fields 

        #region Enums (1) 

        public enum State {Disconnected,Connecting,Connected}

        #endregion Enums 

        #region Constructors (4) 

        public ClientHandler(int id, TTCPClientInterface parent, Socket socket, tWorks.tNetworking.Protocol.Protocol protocol)
        {
            this.id=id;
            this.parent = parent;
            this.protocol = protocol;
            dataHandler = new DataHandler(protocol, this);
            setConnected(socket);
        }

        public ClientHandler(int id, TTCPClientInterface parent, Protocol.Protocol protocol)
        {
            this.id=id;
            this.parent = parent;
            this.protocol = protocol;
            dataHandler = new DataHandler(protocol, this);
            state = State.Disconnected;
        }

        public ClientHandler(int id, TTCPClientInterface parent, Socket socket)
        {
            this.id=id;
            this.parent = parent;
            setConnected(socket);
        }

        public ClientHandler(int id, TTCPClientInterface parent)
        {
            this.id=id;
            this.parent = parent;
            this.protocol = null;
            changeState(State.Disconnected);
        }

        #endregion Constructors 

        #region Delegates and Events (4) 

        // Delegates (2) 

        public delegate void ConnectionLostDelegate(string message);
        public delegate void exceptionDelegate(Exception ex);
        // Events (2) 

        public event exceptionDelegate ConnectionFailed;

        public event ConnectionLostDelegate ConnectionLostEvent;

        #endregion Delegates and Events 

        #region Methods (17) 

        // Public Methods (16) 

        public void connect(string address, int port, int retryInterval, bool reestablish)
        {
            System.Random rand = new Random();
            localPort = rand.Next(40000, 60000);
            IPAddress localIP = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0]; // new IPAddress(Dns.GetHostByName(Dns.GetHostName()).AddressList[0].Address);
            connect(address, port, retryInterval, reestablish, localIP.ToString(), localPort);            
        }

        /// <summary>
        /// Will connect to the address and port specified. If connection failed a new attempt will be made according to the Interval parameter. 
        /// If connection is lost attempts to reastablish it will be made if Reestablish is set to true.
        /// </summary>
        /// <param name="address"></param>
        /// <param name="port"></param>
        /// <param name="retryInterval"></param>
        /// <param name="reestablish"></param>
        public void connect(string address, int port, int retryInterval, bool reestablish, string localAddress, int localPort)
        {
            this.reconnect = reestablish;
            this.address = address;
            this.port = port;
            this.interval = retryInterval;
            this.localAddress = localAddress;
            this.localPort = localPort;
            changeState(State.Connecting);
            connector = new Connector(address, port, this, interval, localPoint, reestablish);
            connector.Connect();
        }

        public void disconnect()
        {
            reconnect = false;
            if (connector != null)
            {
                connector.stopConnecting();
            }
            setDisconnected();
        }

        public void dispose()
        {

        }

        public void failedConnect(Exception e)
        {
            if (ConnectionFailed != null)
                ConnectionFailed(e);
        }

        public int getID()
        {
            return this.id;
        }

        public string getIP()
        {
            return remoteIP;
        }

        public bool isConnected()
        {
            return this.state == State.Connected;
        }

        public void outDataLog(int nbrBytes)
        {
            parent.outDataLog(nbrBytes, id);
        }

        public void preProcessMessage(byte[] data)
        {
            //data = Crypto.Decrypt("a1s2d3", data);
            if(protocol != null)
                dataHandler.addData(data);
            else
                processMessage(data);
        }

        public void processMessage(byte[] data)
        {

            parent.processMessage(data,this);
        }

        public bool sendData(byte[] data)
        {
            if(this.state == State.Connected)
            {
                if (data != null && data.Length > 0)
                {
                    try
                    {
                        //data = Crypto.Encrypt("a1s2d3", data);
                        outputStream.Write(data, 0, data.Length);
                        outputStream.Flush();
                    }
                    catch(Exception e)
                    {
                        System.Diagnostics.Debug.WriteLine("ClientHandler.sendData> " + e.ToString());
                    }
                    //parent.outDataLog(data.Length);
                }
            }
            return true;
        }

        public void setConnected(Socket thisClient)
        {
            socket = thisClient;
            outputStream = new NetworkStream(thisClient);
            input = new TCPInput(outputStream, this);
            remoteIP = this.socket.RemoteEndPoint.ToString();
            changeState(State.Connected);
        }

        public void setDisconnected()
        {
            try
            {
                if (this.state == State.Connected)
                {
                    changeState(State.Disconnected);
                    //socket.Shutdown(SocketShutdown.Both);
                    socket.Close();
                }
            }
            catch { }
            if (reconnect)
                this.connect(address, port, interval, true, localAddress, localPort);
        }

        public void stopConnect()
        {
            connector.stopConnecting();
            changeState(State.Disconnected);
        }

        public override string ToString()
        {
            string returnString = "(D)";
            if(this.state == State.Connected)
                returnString = this.getIP();
            return returnString;
        }
        // Private Methods (1) 

        private void changeState(State state)
        {
            if (this.state == State.Connected && state == State.Disconnected)
            {
                if (ConnectionLostEvent != null)
                    ConnectionLostEvent("Uppkoppling bröts.");
            }
            this.state = state;
            parent.connStateChange(this);
        }

        #endregion Methods 
    }
}

TCPInput.cs, ClientHandler (. ):

using System;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace tWorks.tNetworking.tNetworkingCF
{
    public class TCPInput
    {
        NetworkStream stream;
        ClientHandler client;

        public TCPInput(NetworkStream nS, ClientHandler client)
        {
            stream = nS;
            this.client = client;
            Thread t = new Thread(new ThreadStart(run));
            t.IsBackground = true;
            t.Name = "TCPInput";
            t.Start();
        }

        public void run()
        {
            bool continueRead = true;
            byte[] readBuffer = new byte[32768];
            byte[] receivedBuffer = null;

            int nbrBytesRead = 0;
            int receivedBufferPos = 0;
            while(continueRead)
            {
                try
                {
                    nbrBytesRead = 0;
                    nbrBytesRead = stream.Read(readBuffer, 0, 10000);
                    receivedBuffer = new byte[nbrBytesRead];
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine("TCPInput> Exception when stream.Read: " + e.ToString());
                    continueRead = false;
                }
                if(nbrBytesRead > 0)
                {
                    try
                    {
                        Array.Copy(readBuffer, 0, receivedBuffer, receivedBufferPos, nbrBytesRead);
                    }
                    catch (Exception e)
                    {
                        System.Diagnostics.Debug.WriteLine("TCPInput> Exception when Array.Copy: " + e.ToString());
                        continueRead = false; 
                    }
                    client.preProcessMessage(receivedBuffer);
                }
                else
                {
                                // *** I can break here, the nbrOfBytes read is 0 when this whole thing explodes =)
                    System.Diagnostics.Debug.WriteLine("TCPInput> Number of bytes read == 0! Setting continueRead = false");
                    continueRead = false;
                }

            }
            client.setDisconnected();
        }
    }
}
+3
4

, , 21 , , 22, .

, , ...

+1

( " , 65835 " ) 2^16-1 (65535) - !

( , , kaboom! - ).

, 16- ( ), - . , "" ? (, " ": -)

+1

, "". "". , . , , , .

+1

You are posting questions to me. For example, why do you choose well-known ports for this service? I do not believe in coincidence and suspect that your use of the term partner-in-crime may have more truth than I would like to be associated with.

Then I also wonder why you accept the Windows error, and not the one in MyNetowrking.dll. Of course you have been using this for five years. But he still did not have a level of verification that Microsoft was giving its code.

0
source

Source: https://habr.com/ru/post/1773514/


All Articles