[Help] Socket Exception

06/21/2020 20:55 Mr.Zeko#1
Any one can help me with Socket Exception error

Exception
Code:
System.Net.Sockets.SocketException (0x80004005): An operation was attempted on s
omething that is not a socket
   at System.Net.Sockets.Socket.Select(IList checkRead, IList checkWrite, IList
checkError, Int32 microSeconds)
   at ClassicConquer.Necessaries.ServerSockets.SocketPoll.CheckUp() in d:\Source\ServerSockets\SocketPoll.cs:line 55
SocketPoll
Code:
  public static class SocketPoll
    {
        const int SOCKET_PROCESS_INTERVAL = 20, FD_SETSIZE = 2048;

        public readonly static SafeCollections.SafeList<SecuritySocket> ConnectionPoll = new SafeCollections.SafeList<SecuritySocket>();

        private static ServerSocket[] Sockets;

        public static void Create(string group, params ServerSocket[] _Sockets)
        {
            Sockets = _Sockets;
            var ThreadItem = new ThreadGroup.ThreadItem(SOCKET_PROCESS_INTERVAL, group, CheckUp);
            ThreadItem.Open();
        }

        public static void CheckUp()
        {
            try
            {
                List<Socket> RecSockets = new List<Socket>();
                ///   List<Socket> SendSockets = new List<Socket>();
                //   List<Socket> ErrorSockets = new List<Socket>();
                if (ConnectionPoll.Count > 0 || Sockets.Length > 0)
                {

                    System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
                    timer.Start();

                    foreach (var socket in Sockets)
                    {
                        if (socket == null || socket.IsAlive == false)
                            continue;
                        RecSockets.Add(socket.GetConnection);
                    }

                    foreach (var socket in ConnectionPoll.GetValues())
                    {
                        if (socket.Alive)
                        {
                            RecSockets.Add(socket.Connection);
                        }
                    }
                    //  IntPtr[] readmask = null;
                    try
                    {
                        Socket.Select(RecSockets, null, null, 0);
                        //    int test = WindowsAPI.ws2_32.MySocketSelect(FD_SETSIZE, RecSockets, 100, out readmask);
                    }
                    catch (Exception e)
                    {
                        MyConsole.WriteLine(e.ToString());
                        MyConsole.SaveException(e);
                    }

                    foreach (var socket in ConnectionPoll.GetValues())
                    {
                        try
                        {
                            //  if (readmask != null && WindowsAPI.ws2_32.FD_ISSET(readmask, socket.Connection.Handle))

                            if (RecSockets.Contains(socket.Connection))
                                socket.ReceiveBuffer();
                            socket.HandlerBuffer();


                            while (SecuritySocket.TrySend(socket)) ;
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }

                    }
                    foreach (var socket in Sockets)
                    {
                        try
                        {
                            if (socket == null)
                                continue;

                            //if (readmask != null && WindowsAPI.ws2_32.FD_ISSET(readmask, socket.GetConnection.Handle))
                            if (RecSockets.Contains(socket.GetConnection))
                                socket.Accept();
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                    }
                    timer.Stop();
                    if (timer.ElapsedMilliseconds > 100)
                    {
                        //Console.WriteLine("stamp -> " + timer.ElapsedMilliseconds); 
                    }


                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
06/22/2020 02:06 -impulse-#2
What I suspect is happening is a race condition. There are no synchronization methods used when polling the available connections. Although I believe SafeCollections.SafeList does use synchronization it is of no help because the main issue is the array Sockets. The issue is experienced when those steps happen sequentially.

1. CheckUp is being called
2. RecSockets is built from Sockets and ConnectionPoll
3. A socket from either Sockets array or ConnectionPoll list is disconnected/disposed
4. Execution reaches "Socket.Select(RecvSockets)" at which point the Select method will throw an exception because a non-socket handle was provided in the list (because said socket handle had been disposed)

While one could employ certain synchronization methods to make CheckUp thread-safe, it would not be an optimal solution. The better route would be to allow the OS to control all of it (it's more likely that the system code works better because it had to been tested and has been proven to be efficient).
Windows provides asynchronous socket interfaces even for low level but luckily you don't have to dig deep. A proper usage of C#'s BeginAsync and SendAsync use said underlying async APIs and would yield better results than you synchronizing your code would.