服务器代码(做了简化)class Client:IDisposable
    {
        Socket _client;
        NetworkStream _stream;        byte[] buffer;        bool IsDisposed;        public Client(Socket client)
        {
            this._client = client;
            this._stream = new NetworkStream(client, FileAccess.Read);
            this.buffer = new byte[256];
            this.read();
        }        private void read()
        {
            _stream.BeginRead(buffer, 0, buffer.Length, ReadCallback, null);
        }        private void ReadCallback(IAsyncResult ar)
        {
            int i = _stream.EndRead(ar);
            if (Encoding.Unicode.GetString(buffer, 0, i) == "quit")
                this.Close();
            if (!IsDisposed)
                _stream.BeginRead(buffer, 0, buffer.Length, ReadCallback, null);        }        ~Client()
        {
            Dispose(false);
        }        private void Close()
        {
            Dispose(true);
        }        #region IDisposable 成员        void IDisposable.Dispose()
        {
            Dispose(true);
        }        #endregion        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                //清理托管资源
            }
            //清理非托管资源
            Console.WriteLine("{0}正在释放", this._client.RemoteEndPoint);            _stream.Close();
            _stream = null;
            _client.Shutdown(SocketShutdown.Both);
            _client.Close();
            _client = null;
            IsDisposed = true;            Console.WriteLine("已被释放");
            
        }    }    class Program
    {
        static List<Client> clients = new List<Client>();
        static Socket serverSocket;
        static void Main(string[] args)
        {
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind(new IPEndPoint(Dns.GetHostAddresses(Dns.GetHostName())[0], 5000));
            serverSocket.Listen(100);
            serverSocket.BeginAccept(Accept_Callback, null);            //无限阻塞,为了演示需要
            Thread.Sleep(Timeout.Infinite);
        }        private static void Accept_Callback(IAsyncResult ar)
        {
            Socket client = serverSocket.EndAccept(ar);
            Console.WriteLine(client.RemoteEndPoint);
            clients.Add(new Client(client));            serverSocket.BeginAccept(Accept_Callback, null);
        }
    }

解决方案 »

  1.   


    客户端代码public class NetCommunicator
        {
            /// <summary>
            /// 客户端套接字。
            /// </summary>
            private TcpClient _client;
            private NetworkStream _stream;        public NetCommunicator()
            {
                _client = new TcpClient(new IPEndPoint((Dns.GetHostAddresses(Dns.GetHostName()))[0], 8000));
                _client.Connect(new IPEndPoint(IPAddress.Parse("192.168.0.100"), 5000));
                _stream = _client.GetStream();
            }        ///<summary>
            /// 关闭套接字,释放所有资源。
            /// </summary>
            public void Close()
            {
                try
                {
                    _stream.Write(Encoding.Unicode.GetBytes("quit"), 0, Encoding.Unicode.GetByteCount("quit"));
                }
                catch { }            finally
                {
                    _client.Client.Shutdown(SocketShutdown.Both);
                    _client.Client.Close();
                    _stream.Close();
                    _client.Close();
                    _stream = null;
                    _client = null;
                }
            }    }    class Program
        {        static void Main(string[] args)
            {
                NetCommunicator communicator = new NetCommunicator();
                try
                {
                    //Do something                Console.ReadLine();//敲回车后关闭
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }            finally
                {
                    communicator.Close();
                }        }
        }
    挡在客户端启动程序后 在按回车关闭它  然后再次打开后 
    在_client.Connect(new IPEndPoint(IPAddress.Parse("192.168.0.100"), 5000)); 出现异常未处理 System.Net.Sockets.SocketException
      Message="通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 192.168.0.100:5000"
      Source="System"
      ErrorCode=10048
      NativeErrorCode=10048
      StackTrace:
           在 System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
           在 System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
           在 System.Net.Sockets.TcpClient.Connect(IPEndPoint remoteEP)
           在 client.NetCommunicator..ctor() 位置 C:\Documents and Settings\张威虎\My Documents\Visual Studio 2008\Projects\socketFinalize\client\Program.cs:行号 22
           在 client.Program.Main(String[] args) 位置 C:\Documents and Settings\张威虎\My Documents\Visual Studio 2008\Projects\socketFinalize\client\Program.cs:行号 55
           在 System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
           在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
           在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
           在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
           在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           在 System.Threading.ThreadHelper.ThreadStart()
      InnerException: 但我再等一会后 再次打开客户端(服务端一直开着) 就不出现了
      

  2.   

    我将服务端的ReadCallback改成这样        private void ReadCallback(IAsyncResult ar)
            {
                try
                {
                    int i = _stream.EndRead(ar);
                    if (Encoding.Unicode.GetString(buffer, 0, i) == "quit")
                        this.Close();
                    _stream.BeginRead(buffer, 0, buffer.Length, ReadCallback, null);
                }
                catch (IOException)//当客户端按右上方差号关闭时引发
                {
                    this.Close();
                }        }
        当我直接关闭客户端后(按差号) 再次打开就不出现异常了 让我疑惑的就是 为什么我在finally里面显式的调用close它关不了
    直接结束程序 就能释放