现打算用C#实现这样的需求,程序可以建立多个连接,采用异步接收与发送数据包。
客户端代码封装参照网上的经典写法:
代码如下:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Net.Sockets;
using System.Net;
public class TcpClient
    {
        #region 字段        /// <summary> 
        /// 客户端与服务器之间的会话类 
        /// </summary> 
        private Session _session;        /// <summary> 
        /// 客户端是否已经连接服务器 
        /// </summary> 
        private bool _isConnected = false;        /// <summary> 
        /// 接收数据缓冲区大小64K 
        /// </summary> 
        public const int DefaultBufferSize = 3 * 1024;        /// <summary> 
        /// 通讯格式编码解码器 
        /// </summary> 
        private Coder _coder;        /// <summary> 
        /// 接收数据缓冲区 
        /// </summary> 
        private byte[] _recvDataBuffer = new byte[DefaultBufferSize];        #endregion        #region 事件定义        //需要订阅事件才能收到事件的通知,如果订阅者退出,必须取消订阅        /// <summary> 
        /// 已经连接服务器事件 
        /// </summary> 
        public event NetEvent ConnectedServer;        /// <summary>
        /// 发送数据事件
        /// </summary>
        public event NetEvent SendDatagram;        /// <summary> 
        /// 接收到数据报文事件 
        /// </summary> 
        public event NetEvent ReceivedDatagram;        /// <summary> 
        /// 连接断开事件 
        /// </summary> 
        public event NetEvent DisConnectedServer;
        #endregion        #region 属性        /// <summary> 
        /// 返回客户端与服务器之间的会话对象 
        /// </summary> 
        public Session ClientSession
        {
            get
            {
                return _session;
            }
        }        /// <summary> 
        /// 返回客户端与服务器之间的连接状态 
        /// </summary> 
        public bool IsConnected
        {
            get
            {
                return _isConnected;
            }
        }        /// <summary> 
        /// 编码解码器 
        /// </summary> 
        public Coder ServerCoder
        {
            get
            {
                return _coder;
            }
        }        #endregion        #region 公有方法        /// <summary> 
        /// 默认构造函数,使用默认的编码格式 
        /// </summary> 
        public TcpClient()
        {
            _coder = new Coder(Coder.EncodingMothord.Default);
        }        /// <summary> 
        /// 构造函数,使用一个特定的编码器来初始化 
        /// </summary> 
        /// <param name="_coder">报文编码器</param> 
        public TcpClient(Coder coder)
        {
            _coder = coder;
        }        /// <summary> 
        /// 连接服务器 
        /// </summary> 
        /// <param name="ip">服务器IP地址</param> 
        /// <param name="port">服务器端口</param> 
        public virtual void Connect(string ip, int port)
        {
            if (IsConnected)
            {
                //重新连接 
                Debug.Assert(_session != null);                Close();
            }            Socket newsock = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);            IPEndPoint iep = new IPEndPoint(IPAddress.Parse(ip), port);
            newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);        }        /// <summary> 
        /// 发送数据包 
        /// </summary> 
        /// <param name="datagram">数据包</param> 
        public virtual void Send(byte[] datagram)
        {
            if (datagram.Length == 0)
            {
                return;
            }            if (!_isConnected)
            {
                throw (new ApplicationException("没有连接服务器,不能发送数据"));
            }            _session.ClientSocket.BeginSend(datagram, 0, datagram.Length, SocketFlags.None,
            new AsyncCallback(SendDataEnd), _session.ClientSocket);
        }        /// <summary> 
        /// 关闭连接 
        /// </summary> 
        public virtual void Close()
        {
            if (!_isConnected)
            {
                return;
            }            _session.Close();            _session = null;            _isConnected = false;
        }        #endregion        #region 受保护方法        /// <summary> 
        /// 数据发送完成处理函数 
        /// </summary> 
        /// <param name="iar"></param> 
        protected virtual void SendDataEnd(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            int sent = remote.EndSend(iar);
            Debug.Assert(sent != 0);            if (SendDatagram != null)
            {
                SendDatagram(this, new NetEventArgs(_session));
            }
        }        /// <summary> 
        /// 建立Tcp连接后处理过程 
        /// </summary> 
        /// <param name="iar">异步Socket</param> 
        protected virtual void Connected(IAsyncResult iar)
        {
            Socket socket = (Socket)iar.AsyncState;            socket.EndConnect(iar);            //创建新的会话 
            _session = new Session(socket);            _isConnected = true;            //触发连接建立事件 
            if (ConnectedServer != null)
            {
                ConnectedServer(this, new NetEventArgs(_session));
            }            //建立连接后应该立即接收数据 
            _session.ClientSocket.BeginReceive(_recvDataBuffer, 0,
            DefaultBufferSize, SocketFlags.None,
            new AsyncCallback(RecvData), socket);
        }        /// <summary> 
        /// 数据接收处理函数 
        /// </summary> 
        /// <param name="iar">异步Socket</param> 
        protected virtual void RecvData(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;            try
            {
                int recv = remote.EndReceive(iar);                //正常的退出 
                if (recv == 0)
                {
                    _session.TypeOfExit = Session.ExitType.NormalExit;                    if (DisConnectedServer != null)
                    {
                        DisConnectedServer(this, new NetEventArgs(_session));
                    }                    return;
                }                ICloneable copySession = (ICloneable)_session;                Session clientSession = (Session)copySession.Clone();                clientSession.Datagram = _recvDataBuffer;                ReceivedDatagram(this, new NetEventArgs(clientSession));                //继续接收数据 
                _session.ClientSocket.BeginReceive(_recvDataBuffer, 0, DefaultBufferSize, SocketFlags.None,
                new AsyncCallback(RecvData), _session.ClientSocket);
            }
            catch (SocketException ex)
            {
                //客户端退出 
                if (10054 == ex.ErrorCode)
                {
                    //服务器强制的关闭连接,强制退出 
                    _session.TypeOfExit = Session.ExitType.ExceptionExit;                    if (DisConnectedServer != null)
                    {
                        DisConnectedServer(this, new NetEventArgs(_session));
                    }
                }
                else
                {
                    throw (ex);
                }
            }
            catch (ObjectDisposedException ex)
            {
                //这里的实现不够优雅 
                //当调用CloseSession()时,会结束数据接收,但是数据接收 
                //处理中会调用int recv = client.EndReceive(iar); 
                //就访问了CloseSession()已经处置的对象 
                //我想这样的实现方法也是无伤大雅的. 
                if (ex != null)
                {
                    ex = null;
                    //DoNothing; 
                }
            }        }        #endregion
    }建立多个连接时,代码如下:TcpClient tcp;
            for (int i = 0; i < 3; i++)
            {
                tcp = new TcpClient();
                tcp.Connect("127.0.0.1", 8080);
                tcp.Send(Encoding.Unicode.GetBytes("测试数据"));
            }PS:在断点调试时不报错,不调试则会在这一句throw (new ApplicationException("没有连接服务器,不能发送数据"));报错。
请各位高手指点一二,谢谢!

解决方案 »

  1.   

    没有,能建立单个连接的发送与接收,建立多个TcpClient实例化类,就会报错。还望指教!
      

  2.   

    单连接没有问题,例如如果把下面代码TcpClient tcp;
                for (int i = 0; i < 3; i++)
                {
                    tcp = new TcpClient();
                    tcp.Connect("127.0.0.1", 8080);
                    tcp.Send(Encoding.Unicode.GetBytes("测试数据"));
                }改成TcpClient tcp=new TcpClient(); 
    tcp.Connect("127.0.0.1", 8080);
    tcp.Send(Encoding.Unicode.GetBytes("测试数据"));是可以正常工作的。
      

  3.   

    TcpClient tcp=new TcpClient(); 
    tcp.Connect("127.0.0.1", 8080);连接过后,你得知道是否连接上再发吧。连接方法里面使用的是异步连接,需要等到有结果后再进行操作。
      

  4.   

    你建立多个连接的方式有问题吧.
    你可以在循环外建立一个TcpClient数组,然后再循环内,建立连接.TcpClient tcp = new TcpClient[3]; 
    for (int i = 0; i < 3; i++)
    {
        tcp[i] = new TcpClient();
        tcp[i].Connect("127.0.0.1", 8080);
    }
      

  5.   

    你使用Connect建立连接使用的是异步方式,那么连接建立成功后,应该通过事件通知给应用层,你不能在上面的Connect后直接发送数据,也许连接尚未建立.你需要在连接成功的事件中发送数据.
    ConnectedServer这个事件中Send