服务器内存不足异常,但最麻烦的;事件不被调用,除非我调试

本文关键字:调用 非我 事件 调试 异常 内存不足 服务器 麻烦 | 更新日期: 2023-09-27 18:10:27

我有这个非常奇怪的错误。基本上,只要我添加一行代码Connections.Add(handler);我的程序出问题了。我也得到了错误:

系统。OutOfMemoryException:异常类型的系统。抛出OutOfMemoryException'。在System.Threading.ExecutionContext.CreateCopy ()System.Net.ContextAwareResult.CaptureOrComplete (ExecutionContext&cachedContext, Boolean returnContext)

发生的是,当我添加这段代码,连接仍然被接受,但没有记录在我的日志richtextbox控件。这太奇怪了,我不知道发生了什么。但是,在我的accept事件中删除Connections.Add(handler)行可以解决所有问题。但我需要以某种方式跟踪套接字以便我可以实现ping以保持它们的活动

我的代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Concurrent;
namespace SpybotServer
{  
    public partial class Server : Form
    {  
        public void log(String text)
        {
            logs.InvokeEx(a => a.Text += (text +Environment.NewLine));
        }
        public Server()
        {
            InitializeComponent();            
        }
        private void Server_Load(object sender, EventArgs e)
        {            
            Thread serverThread = new Thread(delegate()
                {
                    Listener.StartListening(9001);
                });
            serverThread.Start();
            heartbeat.Start();
        }
        private void Server_FormClosed(object sender, FormClosedEventArgs e)
        {
            Listener.looping = false;
        }
        private void heartbeat_Tick(object sender, EventArgs e)
        {
            Listener.heartbeat();
        }
    }
    public class StateObject
    {
        public Socket workSocket = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
    }
    public class Listener
    {       
        public static Boolean looping = true;
        private static List<Socket> Connections = new List<Socket>();
        public static void heartbeat()
        {
            Program.MainForm.log("Sending ping...");             
        }
        public static void StartListening(int port)
        {
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 9001);
            Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Program.MainForm.log("Listening on port " + port);
            try
            {
                listener.Bind(localEndPoint);
                listener.Listen(100);
                while (looping)
                {
                    listener.BeginAccept(
                        new AsyncCallback(AcceptCallback),
                        listener);
                }
            }
            catch (Exception e)
            {
                Program.MainForm.log(e.ToString());
            }
        }
        public static void AcceptCallback(IAsyncResult ar)
        {
            Socket listener = (Socket)ar.AsyncState;
            Socket handler = listener.EndAccept(ar);
            StateObject state = new StateObject();
            state.workSocket = handler;
            IPEndPoint ip = handler.RemoteEndPoint as IPEndPoint;                    
            Program.MainForm.log("Accepted connection from " + ip.Address);
            //Connections.Add(handler);
            handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReadCallback), state);
        }
        public static void ReadCallback(IAsyncResult ar)
        {
            String content = String.Empty;
            StateObject state = (StateObject) ar.AsyncState;
            Socket handler = state.workSocket;
            try
            {
                int bytesRead = handler.EndReceive(ar);
                if (bytesRead > 0)
                {
                    state.sb.Append(Encoding.ASCII.GetString(
                        state.buffer, 0, bytesRead));
                    content = state.sb.ToString();                    
                    /*if (content.IndexOf("!@<EOF_END>@!") > -1)
                    {
                        Program.MainForm.log(content);
                    }
                    else
                    {
                        handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                            new AsyncCallback(ReadCallback), state);
                    }*/
                }
            }
            catch (Exception e)
            {
                Program.MainForm.log(e.ToString());
            }
        }

        private static void Send(Socket handler, String data)
        {
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            handler.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback(SendCallback), handler);
        }
        private static void SendCallback(IAsyncResult ar)
        {
            Socket handler = (Socket)ar.AsyncState;
            try
            {                
                int bytesSent = handler.EndSend(ar);
                if (bytesSent <= 0)
                {
                    Program.MainForm.log("Socket has been closed.");
                }
            }
            catch (Exception e)
            {
                Program.MainForm.log(e.ToString());
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }
        }
    }
}

InvokeEx:

using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace SpybotServer
{
    static class ISynchronizeInvokeExtensions
    {
        public static void InvokeEx<T>(this T @this, Action<T> action) where T : ISynchronizeInvoke
        {
            if (@this.InvokeRequired)
            {
                @this.Invoke(action, new object[] { @this });
            }
            else
            {
                action(@this);
            }
        }
    }
}

服务器内存不足异常,但最麻烦的;事件不被调用,除非我调试

从这个回调开始:

public static void AcceptCallback(IAsyncResult ar)

在这个循环中:

while (looping)
{
    listener.BeginAccept(
        new AsyncCallback(AcceptCallback),
        listener);
}

我有90%以上的肯定,你正在不断地将相同的Socket添加到Connections列表中,并且只是以惊人的速度增加列表的大小。将add更改为:

if (Connections.Contains(handler))
{
    Connections.Add(handler);
}

Michael是在正确的轨道上,但没有正确的解决方案。

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

Is(不像Accept)不会阻塞,如果你这样调用它,会发生奇怪的事情。相反,将BeginAccept从循环中取出并从AcceptCallback再次调用它,以便在接受第一个之后可以接受新的连接