下面的代码是从网找到的,能正常运行没有问题,我有一些问题:
1、TcpListener server 这些变量都是局部的,为什么还能正常工作。
2、我如何停止监听服务。private void AcceptCallback(IAsyncResult ar) 
        { 
            TcpListener server = (TcpListener)ar.AsyncState; 
            ClientState state = new ClientState();             // Once the accept operation completes, this callback will 
            // be called. In it, you can create a new TcpClient in much 
            // the same way you did it in the synchronous code you had:             state.client = server.EndAcceptTcpClient(ar);             // We're going to start reading from the client's stream, and 
            // we need a buffer for that:             state.buffer = new byte[4096];             // Note that the TcpClient and the byte[] are both put into 
            // this "ClientState" object. We're going to need an easy 
            // way to get at those values in the callback for the read 
            // operation.             // Next, start a new accept operation so that we can process 
            // another client connection:             server.BeginAcceptTcpClient(AcceptCallback, server);             // Finally, start a read operation on the client we just 
            // accepted. Note that you could do this before starting the 
            // accept operation; the order isn't really important.             state.client.GetStream().BeginRead(state.buffer, 0,state.buffer.Length, ReadCallback, state); 
        }         private void ReadCallback(IAsyncResult ar) 
        { 
            ClientState state = (ClientState)ar.AsyncState; 
            int cbRead = state.client.GetStream().EndRead(ar);             if (cbRead == 0) 
            { 
                // The client has closed the connection 
                return; 
            }
            // Your data is in state.buffer, and there are cbRead 
            // bytes to process in the buffer. This number may be 
            // anywhere from 1 up to the length of the buffer. 
            // The i/o completes when there is _any_ data to be read, 
            // not necessarily when the buffer is full.             // So, for example: 下面的是我的实现。
            SockMsgStruct message = new SockMsgStruct();
            message = (SockMsgStruct)ZhiKe.Serialization.ByteToObj(state.buffer);            StreamWriter f = new StreamWriter("c:/aa.txt",true);
            f.WriteLine(message.MsgUid);
            f.WriteLine(message.sMsg);
            f.WriteLine(message.iMsgType);
            f.Flush();
            f.Close();
            //textBox1.Text = textBox1.Text + strData + "/n/r";            // For ASCII you won't have to worry about partial characters 
            // but for pretty much any other common encoding you'll have to 
            // deal with that possibility, as there's no guarantee that an 
            // entire character will be transmitted in one piece.             // Of course, even with ASCII, you need to watch your string 
            // terminations. You'll have to either check the read buffer 
            // directly for a null terminator, or have some other means 
            // of detecting the actual end of a string. By the time the 
            // string goes through the decoding process, you'll have lost 
            // that information.             // As with the accept operation, we need to start a new read 
            // operation on this client, so that we can process the next 
            // bit of data that's sent:             state.client.GetStream().BeginRead(state.buffer, 0,state.buffer.Length, ReadCallback, state);
        }         private void button1_Click(object sender, EventArgs e)
        {
            Int32 port = int.Parse(txtPort.Text);
            IPAddress localAddr = IPAddress.Parse(cmbAddress.Text);
            TcpListener server = new TcpListener(localAddr, port);
            server.Start();
            // The above is pretty much what you had, cleaned up 
            // a bit. All you have to do at this point is start 
            // an accept operation: 
            server.BeginAcceptTcpClient(AcceptCallback, server); 
        }
  class ClientState
    {
        public TcpClient client;
        public byte[] buffer;
    } 

解决方案 »

  1.   

     button1_Click里面创建TcpListener server ,然后使用异步回调AcceptCallback,“server.BeginAcceptTcpClient(AcceptCallback, server);”它带一个 IAsyncResult 类型的参数,就是说server 对象已经含在这个参数里了。 
     然后看代码
    AcceptCallback(IAsyncResult ar)  
            {  
                TcpListener server = (TcpListener)ar.AsyncState;  
    这里,又从参数里把server 对象取出来了。至于关闭监听的问题,
    private void button1_Click(object sender, EventArgs e) 
            { 
                Int32 port = int.Parse(txtPort.Text); 
                IPAddress localAddr = IPAddress.Parse(cmbAddress.Text); 
                TcpListener server = new TcpListener(localAddr, port); 
    你改成
    TcpListener server =null;
    private void button1_Click(object sender, EventArgs e) 
            { 
                Int32 port = int.Parse(txtPort.Text); 
                IPAddress localAddr = IPAddress.Parse(cmbAddress.Text); 
                server = new TcpListener(localAddr, port); 
             ...
            }
    最后需要关闭的时候,使用server .close()就行了
      

  2.   

    to linus00:这个方法,我用过了。server .close()关闭后,
    我向服务器发送信息,提示 state.client = server.EndAcceptTcpClient(ar); 这行出错。下面的是具体的错误信息
    未处理 System.ObjectDisposedException
      Message="无法访问已释放的对象。\r\n对象名:“System.Net.Sockets.Socket”。"
      Source="System"
      ObjectName="System.Net.Sockets.Socket"
      StackTrace:
           在 System.Net.Sockets.Socket.EndAccept(IAsyncResult asyncResult)
           在 System.Net.Sockets.TcpListener.EndAcceptTcpClient(IAsyncResult asyncResult)
           在 SocketServer_Async.ServerForm.AcceptCallback(IAsyncResult ar) 位置 D:\xxx\应用程序服务\SocketSample\SocketServer_Async\SocketServer_Async\ServerForm.cs:行号 52
           在 System.Net.LazyAsyncResult.Complete(IntPtr userToken)
           在 System.Net.ContextAwareResult.CompleteCallback(Object state)
           在 System.Threading.ExecutionContext.runTryCode(Object userData)
           在 System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
           在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
           在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
           在 System.Net.ContextAwareResult.Complete(IntPtr userToken)
           在 System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
           在 System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
           在 System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
      

  3.   

    这个异常是在关闭TCPListener时一定会引发的,你必须捕获并处理它。