Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / August 2005

Tip: Looking for answers? Try searching our database.

Problem with Sockets

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Alejandro Serrano - 14 Aug 2005 15:22 GMT
Hi, I'm developing a program who needs that user communicate via TCP
over the net. One will be the listener and the other one the client, as
usual. I've implemented the code as two classes deriving from a common
interface. Everything seems to work OK until I use the Close() method.
I've tried both using EndReceive(result) or commenting it. If I use it,
the connection is not closed. If not, both applications close
themselves: the one on the end-point with a error (not an exception, but
an Windows fatal error). The code is below.

Thanks in advance. If someone could help me, I'd be very pleased.

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace ThreatOfChaos.Connection
{
    // This two classes are used in callbacks
    class MessageEventArgs : System.EventArgs
    {
        string message;

        public MessageEventArgs(string Message)
        {
            this.message = Message;
        }

        public string Message
        {
            get
            { return message; }
        }
    }
    class ConnectionEventArgs : System.EventArgs
    {
        Socket socket;

        public ConnectionEventArgs(Socket Socket)
        {
            this.socket = Socket;
        }

        public Socket Socket
        {
            get { return socket; }
        }
    }

    public delegate void MessageReceivedHandler(object sender,
MessageEventArgs e);
    public delegate void ConnectionEstablishedHandler(object sender,
ConnectionEventArgs e);
    public delegate void ConnectionClosedHandler(object sender);

    // This is the interface that both
    // client and server implement.
    public interface IConnection
    {
        event MessageReceivedHandler MessageReceived;
        event ConnectionEstablishedHandler ConnectionEstablished;
        event ConnectionClosedHandler ConnectionClosed;

        Socket Socket { get; }
        void Start(int Port, IPAddress address);
        void Send(byte[] buffer);
        void Send(string data);
        void Close();
    }

    public class SocketPacket
    {
        public Socket Socket;
        public byte[] DataBuffer = new byte[1000000];
    }

    // This is the Client implementation
    public class ClientConnection : IConnection
    {
        public event MessageReceivedHandler MessageReceived;
        public event ConnectionEstablishedHandler ConnectionEstablished;
        public event ConnectionClosedHandler ConnectionClosed;

        Socket client;
        AsyncCallback dataReceived;
        IAsyncResult result;

        public Socket Socket
        {
            get { return client; }
        }

        public void Start(int Port, IPAddress address)
        {
            client = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint endPoint = new IPEndPoint(address, Port);
            client.Connect(endPoint);
            if (client.Connected)
            {
                if (ConnectionEstablished != null)
                {
                    ConnectionEventArgs e = new
ConnectionEventArgs(client);
                    ConnectionEstablished(this, e);
                }
                WaitForData();
            }
            else
            {
                throw new Exception("Client not connected");
            }
        }

        public void WaitForData()
        {
            if (client.Connected)
            {
                if (dataReceived == null)
                    dataReceived = new AsyncCallback(OnDataReceived);

                SocketPacket packet = new SocketPacket();
                packet.Socket = client;
                result = client.BeginReceive(packet.DataBuffer, 0,
                    packet.DataBuffer.Length, SocketFlags.None,
                    dataReceived, packet);
            }
            else
            {
                Close();
            }
        }

        public void OnDataReceived(IAsyncResult asyn)
        {
            SocketPacket packet = (SocketPacket)asyn.AsyncState;
            int iRx = packet.Socket.EndReceive(asyn);
            char[] chars = new char[iRx + 1];
            Decoder d = Encoding.Unicode.GetDecoder();
            int charLen = d.GetChars(packet.DataBuffer, 0,
                iRx, chars, 0);
            string data = new string(chars);

            if (MessageReceived != null)
            {
                MessageEventArgs e = new MessageEventArgs(data);
                MessageReceived(this, e);
            }

            WaitForData();
        }

        public void Send(byte[] buffer)
        {
            if (client.Connected)
            {
                client.Send(buffer);
            }
            else
            {
                Close();
            }
        }

        public void Send(string data)
        {
            byte[] byData = Encoding.Unicode.GetBytes(data);
            Send(byData);
        }

        public void Close()
        {
            client.EndReceive(result);
            client.Close();
            Send("");
            if (ConnectionClosed != null)
                ConnectionClosed(this);
        }
    }

    // This is the Server implementation
    public class ServerConnection : IConnection
    {
        public event MessageReceivedHandler MessageReceived;
        public event ConnectionEstablishedHandler ConnectionEstablished;
        public event ConnectionClosedHandler ConnectionClosed;

        Socket listener;
        Socket workerSocket;
        AsyncCallback dataReceived;
        IAsyncResult result;

        public void Start(int Port, IPAddress address)
        {
            listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, Port);
            listener.Bind(ipLocal);
            listener.Listen(4);
            listener.BeginAccept(new AsyncCallback(OnClientConnect), null);
        }

        public void OnClientConnect(IAsyncResult asyn)
        {
            workerSocket = listener.EndAccept(asyn);
            if (ConnectionEstablished != null)
            {
                ConnectionEventArgs e = new
ConnectionEventArgs(workerSocket);
                ConnectionEstablished(this, e);
            }
           WaitForData(workerSocket);
        }

        public void WaitForData(Socket socket)
        {
            if (socket.Connected)
            {
                if (dataReceived == null)
                    dataReceived = new AsyncCallback(OnDataReceived);

                SocketPacket packet = new SocketPacket();
                packet.Socket = socket;
                result = socket.BeginReceive(packet.DataBuffer, 0,
                    packet.DataBuffer.Length, SocketFlags.None,
                    dataReceived, packet);
            }
            else
            {
                Close();
            }
        }

        public void OnDataReceived(IAsyncResult asyn)
        {
            SocketPacket packet = (SocketPacket)asyn.AsyncState;
            int iRx = packet.Socket.EndReceive(asyn);
            char[] chars = new char[iRx + 1];
            Decoder d = Encoding.Unicode.GetDecoder();
            int charLen = d.GetChars(packet.DataBuffer, 0,
                iRx, chars, 0);
            string data = new string(chars);

            if (MessageReceived != null)
            {
                MessageEventArgs e = new MessageEventArgs(data);
                MessageReceived(this, e);
            }

            WaitForData(packet.Socket);
        }

        public Socket Socket
        {
            get
            {
                return (Socket)listener;
            }
        }

        public void Send(byte[] buffer)
        {
            if (workerSocket.Connected)
            {
                workerSocket.Send(buffer);
            }
            else
            {
                Close();
            }
        }

        public void Send(string data)
        {
            byte[] byData = Encoding.Unicode.GetBytes(data);
            Send(byData);
        }

        public void Close()
        {
            workerSocket.EndReceive(result);
            workerSocket.Close();
            listener.Close();
            if (ConnectionClosed != null)
                ConnectionClosed(this);
        }
    }
}
Lee Gillie - 16 Aug 2005 06:32 GMT
There is no way to cancel a pending asynchronous I/O once queued.

For the listener I will do a fake connection to self to cause the accept
to complete and then close.

You should be able to call Shutdown and then Close. It sounds like Close
should cancel any pending sends or receives but I have found it to be
problematic. I will often poll availability of data. But when I must use
asynchronous I/O, and if it times out, and I need to cancel, I close
without shutdown, and catch the exceptions resulting on the end-receive.

Not sure if that is what the doctor ordered, but it seems to work for me.

> Hi, I'm developing a program who needs that user communicate via TCP
> over the net. One will be the listener and the other one the client, as
[quoted text clipped - 284 lines]
>     }
> }

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.