0

everyone. I had written one TCP server program in C# as following, after running it and using jmeter to test it with 1000 threads in 1 second(In such condition, I type the backlog size as 10000). there are about 800 connection ready but others fail with "connection refused.", Could anyone give me some advices?

`

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Socket listenSocket;
        private static ArrayList g_fdlist = new ArrayList();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void btn_confirm_Click(object sender, RoutedEventArgs e)
        {
            var port = Convert.ToInt32(tb_port.Text);
            var backlog = Convert.ToInt32(backlogSize.Text);
            start_socket_server(port, backlog);
            //start_socket_server_selectmode(port, backlog);
        }
        #region select
        private void start_socket_server_selectmode(int port, int backlog)
        {
            if (listenSocket != null)
            {
                listenSocket.Close();
                listenSocket = null;
            }

            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
            listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            listenSocket.Bind(localEndPoint);
            listenSocket.Listen(backlog);
            System.Console.WriteLine(fetchcurrentTime() + ": Start Listen in " + port + ", " + backlog);

            Thread t = new Thread(new ThreadStart(workThread));
            t.Start();

            while (true)
            {
                Socket s = listenSocket.Accept();
                System.Console.WriteLine(fetchcurrentTime() + ": Accept connect " + s.RemoteEndPoint.ToString());
                g_fdlist.Add(s);
            }
        }
        private void workThread()
        {
            ArrayList selectFDlist = new ArrayList();
            while (true)
            {
                selectFDlist.Clear();
                for (int i=0; i<g_fdlist.Count; ++i)
                {
                    selectFDlist.Add(g_fdlist[i]);
                }
                if (selectFDlist.Count <= 0)
                {
                    continue;
                }

                Socket.Select(selectFDlist, null, null, 1);
                int num = selectFDlist.Count;
                byte[] buf = new byte[100];
                foreach(Socket s in selectFDlist)
                {
                    int retlen = s.Receive(buf);
                    if(retlen > 0)
                    {
                        System.Console.WriteLine(fetchcurrentTime() + ": Receive data from " + s.RemoteEndPoint.ToString());
                        
                        Thread.Sleep(10000);
                    } else
                    {
                        System.Console.WriteLine(fetchcurrentTime() + ": socket is closed. " + s.RemoteEndPoint.ToString());
                        s.Shutdown(SocketShutdown.Both);
                        s.Close();
                        g_fdlist.Remove(s);
                    }
                }
            }
        }
        #endregion select

        #region Socket Listen->Accept->Receive->Process
        private void start_socket_server(int port, int backlog)
        {
            if (listenSocket != null)
            {
                listenSocket.Close();
                listenSocket = null;
            }

            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
            listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

            listenSocket.Bind(localEndPoint);
            listenSocket.Listen(backlog);

            System.Console.WriteLine(fetchcurrentTime() + ": Start Listen in " + port + ", " + backlog);
            StartAccept();
        }

        internal string fetchcurrentTime()
        {
            return DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff:ffffff");
        }
        internal void StartAccept()
        {
            System.Console.WriteLine(fetchcurrentTime() + ": StartAccecpt. =================");
            SocketAsyncEventArgs acceptEventArg = CreateNewSaeaForAccept();
            try
            {
                bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);

                if (!willRaiseEvent)
                {
                    ProcessAccept(acceptEventArg);
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(fetchcurrentTime() + ": StartAccept" + ex.Message + "\r\n" + ex.StackTrace);
                StartAccept();
            }
        }

        private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
        {
            ProcessAccept(e);
        }

        internal SocketAsyncEventArgs CreateNewSaeaForAccept()
        {
            //Allocate the SocketAsyncEventArgs object. 
            var acceptEventArg = new SocketAsyncEventArgs();
            acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);

            return acceptEventArg;
        }

        private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs)
        {
            System.Console.WriteLine(fetchcurrentTime() + ": ProcessAccept. ++++++++++++++");
            if (acceptEventArgs.SocketError != SocketError.Success)
            {
                System.Console.WriteLine(fetchcurrentTime() + ": connect error:acceptEventArgs.SocketError != SocketError.Success,SocketErrorType:" + acceptEventArgs.SocketError.ToString());
                StartAccept();
                return;
            }

            StartAccept();
            System.Console.WriteLine(fetchcurrentTime() + ": Receive Connect " + acceptEventArgs.AcceptSocket.RemoteEndPoint.ToString());
            Thread.Sleep(30000);

            SocketAsyncEventArgs tupleReceiveSendEventArgs = new SocketAsyncEventArgs();
            tupleReceiveSendEventArgs.Completed += IO_Completed;
            tupleReceiveSendEventArgs.AcceptSocket = acceptEventArgs.AcceptSocket;
            acceptEventArgs.AcceptSocket = null;

            StartReceive(tupleReceiveSendEventArgs);
        }

        void IO_Completed(object sender, SocketAsyncEventArgs e)
        {
            // determine which type of operation just completed and call the associated handler
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Receive:
                    {
                        ProcessReceive(e);
                        break;
                    }
                case SocketAsyncOperation.Send:
                    {
                        break;
                    }
                default:
                    {
                        //This exception will occur if you code the Completed event of some
                        //operation to come to this method, by mistake.
                        throw new ArgumentException("The last operation completed on the socket was not a receive or send");
                    }

            }
        }

        private void StartReceive(SocketAsyncEventArgs receiveEventArgs)
        {

            try
            {//debug
                byte[] buff = new byte[100];
                if (receiveEventArgs.AcceptSocket.Connected)
                {
                    receiveEventArgs.AcceptSocket.Receive(buff);
                }
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(fetchcurrentTime() + ": StartReceive" + "\r\n" + ex.Message + "\r\n" + ex.StackTrace);
            }

        }
        private void ProcessReceive(SocketAsyncEventArgs receiveEventArgs)
        {
            try
            {
                if (receiveEventArgs.SocketError != SocketError.Success)
                {
                    Console.WriteLine(fetchcurrentTime() + ": Process Receive SocketError.");
                    return;
                }

                if (receiveEventArgs.BytesTransferred == 0)
                {
                    Console.WriteLine(fetchcurrentTime() + ": Process Receive BytesTransferred is 0.");
                    return;
                }


                Int32 remainingBytesToProcess = receiveEventArgs.BytesTransferred;
                int availableBytes = remainingBytesToProcess;
                var byteArrayIn = new byte[availableBytes];

        
                Buffer.BlockCopy(receiveEventArgs.Buffer, 0, byteArrayIn, 0, remainingBytesToProcess);
                StartReceive(receiveEventArgs);
            }
            catch (Exception ex)
            {
                Console.WriteLine(fetchcurrentTime() + ": ProcessReceive" + ex.Message + "\r\n" + ex.StackTrace);
            }
        }
        #endregion Socket Listen->Accept->Receive->Process
    }
}

`

1, The backlog in Listen() is more than the concurrency number, but it seems invalid?

2, How to process the concurrency request successfully?

Theodore
  • 1
  • 1
  • *"1, The backlog in Listen() is more than the concurrency number, but it seems invalid"* - backlog is only a suggestion. You cannot set it to arbitrary high numbers and hope it will work. Apart from that if the system or process might run out of resources or limits (memory, file descriptors ...) – Steffen Ullrich Nov 28 '22 at 12:07
  • `bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);` Why did you chose the weirdest overload of them all? You could just `await` one of the `Task` returning ones in a loop and be done (roughly). – Fildor Nov 28 '22 at 12:22
  • In such case, the resources usage rate is less than 40%. – Theodore Nov 29 '22 at 01:19

0 Answers0