views:

163

answers:

1

I'm working on a client/server application in C#, and I need to get Asynchronous sockets working so I can handle multiple connections at once. Technically it works the way it is now, but I get an OutOfMemoryException after about 3 minutes of running. MSDN says to use a WaitHandler to do WaitOne() after the socket.BeginAccept(), but it doesn't actually let me do that. When I try to do that in the code it says WaitHandler is an abstract class or interface, and I can't instantiate it. I thought maybe Id try a static reference, but it doesnt have teh WaitOne() method, just WaitAll() and WaitAny(). The main problem is that in the docs it doesn't give a full code snippet, so you can't actually see what their "wait handler" is coming from. its just a variable called allDone, which also has a Reset() method in the snippet, which a waithandler doesn't have.

After digging around in their docs, I found some related thing about an AutoResetEvent in the Threading namespace. It has a WaitOne() and a Reset() method. So I tried that around the while(true) { ... socket.BeginAccept( ... ); ... }. Unfortunately this makes it only take one connection at a time. So I'm not really sure where to go. Here's my code:

 class ServerRunner
    {
        private Byte[] data = new Byte[2048];
        private int size = 2048;
        private Socket server;
        static AutoResetEvent allDone = new AutoResetEvent(false);

        public ServerRunner()
        {
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Any, 33333);
            server.Bind(iep);
            Console.WriteLine("Server initialized..");
        }

        public void Run()
        {

            server.Listen(100);
            Console.WriteLine("Listening...");
            while (true)
            {
                //allDone.Reset();
                server.BeginAccept(new AsyncCallback(AcceptCon), server);
                //allDone.WaitOne();
            }
        }

        void AcceptCon(IAsyncResult iar)
        {
            Socket oldserver = (Socket)iar.AsyncState;
            Socket client = oldserver.EndAccept(iar);
            Console.WriteLine(client.RemoteEndPoint.ToString() + " connected");
            byte[] message = Encoding.ASCII.GetBytes("Welcome");
            client.BeginSend(message, 0, message.Length, SocketFlags.None, new AsyncCallback(SendData), client);
        }

        void SendData(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;
            int sent = client.EndSend(iar);
            client.BeginReceive(data, 0, size, SocketFlags.None, new AsyncCallback(ReceiveData), client);
        }

        void ReceiveData(IAsyncResult iar)
        {
            Socket client = (Socket)iar.AsyncState;
            int recv = client.EndReceive(iar);
            if (recv == 0)
            {
                client.Close();
                server.BeginAccept(new AsyncCallback(AcceptCon), server);
                return;
            }
            string receivedData = Encoding.ASCII.GetString(data, 0, recv);
            //process received data here
            byte[] message2 = Encoding.ASCII.GetBytes("reply");
            client.BeginSend(message2, 0, message2.Length, SocketFlags.None, new AsyncCallback(SendData), client);
        }
    }