View Single Post
Old 02-17-2007, 08:44 AM   #1 (permalink)
Cheetah2003
Forum Novice
 
Cheetah2003's Avatar
 
Join Date: Jun 2006
Location: Laramie, Wyoming
Age: 37
Posts: 360
Send a message via ICQ to Cheetah2003 Send a message via AIM to Cheetah2003 Send a message via MSN to Cheetah2003 Send a message via Yahoo to Cheetah2003
Default Socket methods... am I just stupid?

Working on my RunUO Remote GUI thing...

So, basically, I'm doing async socket operations.

When I push a connect button on my form, I start by doing an async Dns.GetHostEntry to resolve the address of the server.

When it completes, I begin an async connect. Code:
Code:
        #region Connecting and DNS
        private void GetHostEntryCallback(IAsyncResult ar)
        {
            try
            {
                IPHostEntry e = Dns.EndGetHostEntry(ar);
                if (e.AddressList.Length == 0)
                    throw new Exception("No address associated with hostname.");
                m_Server.Address = e.AddressList[0];
                BeginInternalConnect();
            }
            catch (Exception e)
            {
                QueueMessage(String.Format("[!] Resolve failed: {0}", e.Message));
            }
        }

        public void BeginConnect()
        {
            IPAddress addr = null;
            try
            {
                addr = IPAddress.Parse(m_Server.ServerHostName);
            }
            catch
            {
                addr = null;
            }

            if (addr == null)
            {
                QueueMessage(String.Format("[+] Resolving {0}...", m_Server.ServerHostName));
                Dns.BeginGetHostEntry(m_Server.ServerHostName, new AsyncCallback(GetHostEntryCallback), null);
            }
            else
            {
                m_Server.Address = addr;
                BeginInternalConnect();
            }
        }

        public void BeginInternalConnect()
        {
            QueueMessage(String.Format("[+] Connecting to {0}...", m_Server.Address.ToString()));
            IPEndPoint hostPoint = new IPEndPoint(m_Server.Address, m_Server.ServerPort);

            try
            {
                m_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                m_Socket.BeginConnect(hostPoint, new AsyncCallback(ConnectCallback), null);
            }
            catch (Exception e)
            {
                QueueMessage(String.Format("[!] Can't connect: {0}", e.Message));
                m_Socket.Close();
                m_Socket = null;
            }
        }

        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                m_Socket.EndConnect(ar);
                m_Connected = true;
                QueueMessage(String.Format("[+] Connected to {0} ({1})", m_Server.ServerHostName, m_Server.Address));
                m_Server.ConnectedAt = DateTime.Now;
            }
            catch (SocketException e)
            {
                m_Socket.Close();
                m_Socket = null;
                QueueMessage(String.Format("[!] Can't connect: {0}", e.Message));
            }
            catch
            {
                m_Socket.Close();
                m_Socket = null;
                QueueMessage("[!] Unknown error.  Can't connect!");
            }
        }
        #endregion
Entry point is BeginConnect(), which is called from another class.

Now, the problem is, sometimes I get this really annoying SocketException, goes like "The attempted operation is not supported for the type of object referenced."

The description from MSDN goes: "Operation not supported. The attempted operation is not supported for the type of object referenced. Usually this occurs when a socket descriptor to a socket that cannot support this operation is trying to accept a connection on a datagram socket."

It doesn't make a lot of sense. I'm not using a datagram socket, obviously. When I push connect the first time, I always get that exception thrown from BeginConnect, but if I push it again right after that, it works.

Getting it out of other WinSock functions too, like Disconnect. Really puzzling. So, am I just stupid? Something I'm not doing right?

I've tried it every different way I could think of. First I tried changing the way I use BeginConnect, by using a string to let it resolve itself, same thing. I tried a IPAddress instead of IPEndPoint. Same thing.

I thought maybe calling the BeginInternalConnect from the DNS callback might be a problem, so I tried having my worker thread do the call to BeginInternalConnect when the DNS was finished. Same thing.

Tried making ConnectCallback static and passing a reference to the object via AsyncResult, so I can access data from the instance. Same thing.

Any advise or insight would be greatly appreciate!
__________________
Take a walk on The Wild side.
Cheetah2003 is offline   Reply With Quote