如何使用套接字侦听器类修复性能问题?

时间:2016-10-07 16:07:12

标签: c# asp.net sockets

我是TCP / IP编程的新手。我使用Microsoft文档和我在网上找到的一个例子创建了一个监听器。

我创建了一个使用本地IP侦听端口的程序。

当一条消息最终进入时,程序立即达到100%负载并停留在那里,不幸的是我不知道如何阻止它。我假设我必须使用ManualResetEvent但是当我尝试实现此功能时,网页就不会加载。

我的实现如下:(如果有人想知道,端口是随机端口)

public static class Listener 
{

    private const int bufferSize = 2048;
    private static byte[] buffer = new byte[bufferSize];
    private static Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    public static void StartListening()
    {
        //Gets local machine IP address
        string ip = GetLocalIPAddress();
        //Creates the IPADDRESS
        IPAddress ipAddress = IPAddress.Parse(ip);
        //Creates a local end point for .Bind(xxx)
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 1322);
        Socket listenerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        try
        {

            //Binds to local machines IP with port 1322
            listener.Bind(localEndPoint);
            //Places socket in a listening state
            listener.Listen(0);

            listener.BeginAccept(new AsyncCallback(AcceptCallback), null);


        }
        catch (Exception e)
        {
            //Throw exception

        }

    }

    private static void CloseSocket()
    {
        listener.Shutdown(SocketShutdown.Both);
        listener.Close();
    }

    public static void AcceptCallback(IAsyncResult ar)
    {


        //Socket casted to async state
        Socket listenerSocket = (Socket)ar.AsyncState;

        try
        {
            //Try end accept
            listenerSocket = listener.EndAccept(ar);
        }catch(Exception e)
        {
            //Throw exception

        }
        //Receive data
        listenerSocket.BeginReceive(buffer, 0, bufferSize, SocketFlags.None, new AsyncCallback(ReadCallBack), listenerSocket);
        listener.BeginAccept(new AsyncCallback(AcceptCallback), null); 
    }

    public static void ReadCallBack(IAsyncResult ar)
    {
        Socket listenerSocket = (Socket)ar.AsyncState;

        int received = 0;
        try
        {
            //Amount of bytes that has been sent
            received = listenerSocket.EndReceive(ar);
        }catch(Exception e)
        {
            listener.Close();

        }
        //Create byte array for encoding
        byte[] bytes = new Byte[received];
        Array.Copy(buffer,bytes,received);
        string recievedMessage = Encoding.ASCII.GetString(bytes);
        if (received > 0)
        {
            //do task input
            System.Diagnostics.Debug.WriteLine(recievedMessage);
        }
        //work on this
        listenerSocket.BeginReceive(buffer, 0 , bufferSize, SocketFlags.None, new AsyncCallback(ReadCallBack), listenerSocket);



    }

    private static string GetLocalIPAddress()
    {
        var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily == AddressFamily.InterNetwork)
            {
                return ip.ToString();
            }
        }
        throw new Exception("Local IP Address Not Found!");
    }

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

一些问题

  1. 您没有将侦听器套接字传递给BeginAccept。

    listener.BeginAccept(new AsyncCallback(AcceptCallback), null);
    

    Socket listenerSocket = (Socket)ar.AsyncState;
    
  2. 为什么要阅读Socket listenerSocket = (Socket)ar.AsyncState; ??

  3. 您在listenerSocket方法中构建StartListening,但您没有使用它。

  4. 错误

    当您关闭“监听器”(ServerClientSocket)时,您不应再次呼叫BeginReceive。只需return

    当套接字received == 0关闭时,请勿启动BeginReceive。这就是它永远循环的原因......开始/结束接收直接返回received == 0

    public static void ReadCallBack(IAsyncResult ar)
    {
        Socket listenerSocket = (Socket)ar.AsyncState;
    
        int received = 0;
        try
        {
            //Amount of bytes that has been sent
            received = listenerSocket.EndReceive(ar);
        }catch(Exception e)
        {
            received = 0;
        }
    
        if(received == 0)
        {
            listener.Close();
            return;
        }
    
        //Create byte array for encoding
        byte[] bytes = new Byte[received];
        Array.Copy(buffer,bytes,received);
        string recievedMessage = Encoding.ASCII.GetString(bytes);
        if (received > 0)
        {
            //do task input
            System.Diagnostics.Debug.WriteLine(recievedMessage);
        }
        //work on this
        listenerSocket.BeginReceive(buffer, 0 , bufferSize, SocketFlags.None, new AsyncCallback(ReadCallBack), listenerSocket);
    }
    

    注意

    TCP / IP套接字是流式套接字,因此您永远不会知道您是否收到了完整的数据包,甚至是两个。您需要知道收到了完整的消息。经常使用PreLength协议。写一个表示后续数据量的值。

答案 1 :(得分:0)

我看到你传递0作为Socket.Listen方法的参数,不确定这是否是导致问题的原因,但是值得尝试将其更改为100

public void Listen(int backlog)

int backlog:挂起连接队列的最大长度。

msdn:https://msdn.microsoft.com/nl-nl/library/system.net.sockets.socket.listen(v=vs.110).aspx