[Mono-list] Problems with asyncronous tcp server?

Řyvind Hvamstad oyvind@hvamstad.net
Sun, 04 Jan 2004 03:03:04 +0100


--=-/Mn+YA+KWmNrXcZ3/KXy
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Hi, I'm having problems with a piece of code I wrote that handles tcp
requests asyncronously. It seems to hang on the call to EndInvoke(). The
code works fine with the 0.26 distro, but not from a fresh cvs build. I
will attach a test case and hopefully someone can verify this as a bug,
or set me straight... :)
--=20
=D8yvind Hvamstad <oyvind@hvamstad.net>

--=-/Mn+YA+KWmNrXcZ3/KXy
Content-Disposition: attachment; filename=TcpTezt.cs
Content-Type: text/plain; name=TcpTezt.cs; charset=
Content-Transfer-Encoding: 7bit

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;

namespace TcpTezt
{
	public delegate void TcpAcceptEventHandler(Object sender, Socket socket);

	public class TcpServer
	{
		public event TcpAcceptEventHandler Accept;  

		protected TcpAsyncListener listener;

		private IPAddress address;
		private IPEndPoint endpoint;

		private bool stop = false;
		
		public TcpServer(int port)
		{
			this.endpoint = new IPEndPoint(IPAddress.Any, port);
		}

		public static int Main()
		{
			TcpServer ts = new TcpServer(8080);
			ts.Start();
			Console.ReadLine();
			return 0;
		}

		public void Start()
		{
			listener = new TcpAsyncListener(endpoint);
			listener.Start();
			listener.BeginAcceptSocket(new AsyncCallback(this.OnAcceptSocket), listener);
			
			endpoint.Port = listener.LocalEndPoint.Port;
			
		}
		
		protected virtual void OnAcceptSocket(IAsyncResult result)
		{
			try {
				if ( stop == false ) {
					TcpAsyncListener listener = (TcpAsyncListener)result.AsyncState;
					Socket socket = listener.EndAcceptSocket(result);

					listener.BeginAcceptSocket(new AsyncCallback(this.OnAcceptSocket), listener);
					if (socket != null) {
						if (null != Accept) {
							Accept(this, socket);
						}
						else {
							socket.Shutdown(SocketShutdown.Both);
							socket.Close();
						}
					}
				}
			} catch (Exception e) {
				Console.WriteLine(e.ToString());
			}
		}
    
		public virtual void Stop()
		{
			stop = true;
			this.listener.Stop();
      		}
	}

	public class TcpAsyncListener : TcpListener
	{

		private delegate Socket AcceptSocketDelegate();

		private delegate TcpClient AcceptTcpClientDelegate();
    
		private AcceptSocketDelegate acceptSocket;

		private AcceptTcpClientDelegate acceptTcpClient;

		public TcpAsyncListener(IPEndPoint endpoint) : base(endpoint)
		{
		}

		public TcpAsyncListener(IPAddress address, int port) : base(address,port)
		{
		}
    
		public IAsyncResult BeginAcceptSocket(AsyncCallback callback,Object state)
		{
			if (acceptSocket == null)
				acceptSocket = new AcceptSocketDelegate(this.AcceptSocket);

			return acceptSocket.BeginInvoke(callback, state);
		}

		public IAsyncResult BeginAcceptTcpClient(AsyncCallback callback,Object state)
		{
			if (null == acceptTcpClient)
				acceptTcpClient = new AcceptTcpClientDelegate(this.AcceptTcpClient);
      
			return acceptTcpClient.BeginInvoke(callback,state);
		}


		// The code seems to hang right here.. But it works with 0.26
		//
		//
		public Socket EndAcceptSocket(IAsyncResult result)
		{
			Console.WriteLine("{0}: Calling EndInvoke", "EndAcceptSocket");
			Socket s = acceptSocket.EndInvoke(result);
			Console.WriteLine("{0}: EndInvoke finished", "EndAcceptSocket");
			return s;
		}

		public TcpClient EndAcceptTcpClient(IAsyncResult result)
		{
			return acceptTcpClient.EndInvoke(result);
		}

		public IPEndPoint LocalEndPoint
		{
			get {
				return (IPEndPoint)this.Server.LocalEndPoint;
			}
		}
	}
}

--=-/Mn+YA+KWmNrXcZ3/KXy--