0

I am trying to send message through sockets in 5 seconds intervals.

In order to test it, I have basic server socket (which will listen to incoming calls) implementation:

    public static void StartListening()
    {
        // Data buffer for incoming data.
        byte[] bytes = new Byte[1024];

        // Establish the local endpoint for the socket.  
        // Dns.GetHostName returns the name of the   
        // host running the application.  
        IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
        IPAddress ipAddress = ipHostInfo.AddressList[0];
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);

        // Create a TCP/IP socket.  
        Socket listener = new Socket(ipAddress.AddressFamily,
            SocketType.Stream, ProtocolType.Tcp);

        // Bind the socket to the local endpoint and   
        // listen for incoming connections.  
        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(10);

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

                // An incoming connection needs to be processed.  
                while (true)
                {
                    bytes = new byte[1024];
                    int bytesRec = handler.Receive(bytes);
                    data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
                    //if (data.IndexOf("<EOF>") > -1)
                    //{
                        break;
                    //}
                }

                // Show the data on the console.  
                Console.WriteLine("Text received : {0}", data);

                // Echo the data back to the client.  
                //byte[] msg = Encoding.ASCII.GetBytes(data);

                // handler.Send(msg);
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        Console.WriteLine("\nPress ENTER to continue...");
        Console.Read();

    }

And the socket, which sends messages I implemented in many ways, none of them worked, I finally was advised to connect and close sockets every time I use them (not every 5 second it will be used - some conditions need to be satisfied in order to make a connection). Anyway, I end up with something like this:

    private static void CheckDbAndSendMessage()
    {
        var entities = // custom ORM read from DB ;

        // no new records
        if (entities.Count == 0)
            return;

        HashSet<string> messages = new HashSet<string>();
        foreach (var entity in entities)
        {
            messages.Add(entity.Description + " --- " + entity.Operator);
            entity.Status = 10;
        }

        try
        {
            SendMessage(messages);
        }
        catch(Exception ex)
        {
            //implemented error handling
        }
    }

    /// <summary>
    /// Sends messages over specified channel.
    /// </summary>
    /// <param name="messages"></param>
    /// <exception cref="Exception">Thrown when socket connections fails.</exception>
    private static void SendMessage(HashSet<string> messages)
    {
        _sender.Connect(_remoteEP);
        foreach (var message in messages)
        {
            _sender.Send(System.Text.Encoding.ASCII.GetBytes(message));
        }

        // When app stops, it will be released.
        _sender.Shutdown(SocketShutdown.Both);
        _sender.Close();

    }

When I run it like this, _sender.Close() will destroy socket, as stated here. So, first connection will be made, but then I will get an ObjectDisposedexception on another call. Ok, so I removed that line, and used only _sender.Shutdown(SocketShutdown.Both) and got exception on second connection saying:

After disconnecting the socket, you can reconnect only asynchronously from a different EndPoint.

So, what is the right way to solve it? I spent hours and got nowhere...

Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
  • One socket = one TCP/IP connection. If you want to keep sending data over one connection, don't close the socket. Don't shut it down either, of course. If you got the socket from an `Accept` call, there's no need to `Connect` it (it's already connected). And take care that neither `Send` nor `Receive` are required to send or receive the exact amount of bytes you specify. In general, using `TcpListener` and `TcpClient` is simpler than working with raw sockets. – Jeroen Mostert Feb 15 '18 at 11:41
  • @JeroenMostert Thanks for remarks. About reading exact amount of bytes - for testing I send really small messages :) <100 bytes, that's the reason for such implementation. – Michał Turczyn Feb 15 '18 at 11:42

0 Answers0