Tcp Socket异步通讯实例

    /// <summary>
    /// Socket客户端实体类,作用发送和接收数据包
    /// </summary>
    public class SocketHelper
    {
        /// <summary>
        /// 端IP地址和端口号
        /// </summary>
        /// <param name="ipAdress">IP</param>
        /// <param name="port">端口号</param>
        public SocketHelper(string ipAdress, int port)
        {
            try
            {
                //远程终端
                _RemoteEP = new IPEndPoint(IPAddress.Parse(ipAdress), port);
                //建立客户端
                _Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //确保可以重复使用套接字
                _Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            }
            catch (ArgumentException ae)
            {
                if (OnError != null)
                    OnError("远程连接IP和端口号错误:" + ae.Message, _Client, 0);
                Console.WriteLine("远程连接IP和端口号错误:" + ae.Message);
            }
            catch (SocketException ex)
            {
                if (OnError != null)
                    OnError("使用套接字出错:" + ex.Message, _Client, 0);
                Console.WriteLine("使用套接字出错:" + ex.Message);
            }
        }

        #region methods
        /// <summary>
        /// socket通信机连接函数
        /// </summary>
        public bool Connect()
        {
            try
            {
                //连接标识
                bool isConnect = false;
                //调用系统连接函数
                _Client.BeginConnect(_RemoteEP, new AsyncCallback(ConnectCallback), _Client);
                //设置一个等待时间
                isConnect = connectDone.WaitOne(100);
                if (isConnect)
                {
                    connectInfo = "连接成功!";
                    Console.WriteLine(connectInfo);
                }
                else
                {
                    connectInfo = "连接失败!";
                    Console.WriteLine(connectInfo);
                }
                return isConnect;
            }
            catch (ObjectDisposedException ex)
            {
                if (OnError != null)
                    OnError(ex.Message, _Client, 0);
                return false;
            }
        }
        /// <summary>
        /// socket连接返回函数
        /// </summary>
        /// <param name="ar">表示异步操作的状态</param>
        private static void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                // 获取socket连接实例 
                Socket client = (Socket)ar.AsyncState;
                // 完成连接过程.
                client.EndConnect(ar);
                // 置位连接完成标志
                connectDone.Set();
                // 得到连接成功信息
                connectInfo = "连接成功!";
            }
            catch (Exception e)
            {
                // 得到连接失败信息
                connectInfo = e.ToString();
                // 结束连接
                connectDone.Reset();
            }
        }
        /// <summary>
        /// socket通信机关闭函数
        /// </summary>
        public void Close()
        {
            try
            {
                if (_Client != null)
                {
                    //如果仍然产生通信信息,则禁用
                    if (_Client.Connected)
                    {
                        _Client.Shutdown(SocketShutdown.Both);
                        _Client.Disconnect(true);
                    }
                    //关闭socket通信
                    _Client.Close();

                    //获得关闭成功信息
                    closeInfo = "通信机已关闭!";
                }
            }
            catch (Exception e)
            {
                //获得关闭通信失败信息
                closeInfo = e.ToString();
                _Client.Disconnect(true);
            }
        }
        /// <summary>
        /// 数据发送函数
        /// </summary>
        /// <param name="messageSend">需发送的信息</param>
        /// <returns>
        /// 返回发送是否成功值
        /// </returns>
        public bool Send(String messageSend)
        {
            //将数据转换成Byte型ASCII码。
            byte[] byteData = Encoding.ASCII.GetBytes(messageSend);

            try
            {
                // 向远程设备(Server)发送数据.
                _Client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), _Client);
                sendInfo = "发送成功!";
                Console.WriteLine(sendInfo);
            }
            catch (SocketException se)
            {
                //设置发送产生错误信息
                sendInfo = "发送失败:" + se.Message;
                Console.WriteLine(sendInfo);
                if (OnError != null)
                    OnError(se.Message, _Client, 0);
                return false;
            }
            //发送标志事件等待
            sendDone.WaitOne();
            //返回真
            return (true);
        }
        /// <summary>
        /// 数据发送返回函数
        /// </summary>
        /// <param name="ar">表示异步操作的状态</param>
        private static void SendCallback(IAsyncResult ar)
        {
            try
            {
                // 获取socket连接实例
                Socket Client = (Socket)ar.AsyncState;
                // 对远程设备发送数据完成
                int bytesSent = Client.EndSend(ar);
                //置位发送完成标志
                sendDone.Set();
                // 获得发送完成信息
                sendInfo = "发送已完成!";
            }
            catch (Exception e)
            {
                //得到发送失败信息
                sendInfo = e.ToString();
                //结束发送标志
                sendDone.Reset();
            }
        }
        /// <summary>
        /// 数据接收函数
        /// </summary>
        /// <param name="client">已连接的socket通信机实例(客户端)</param>
        /// <returns>
        /// 返回接收数据
        /// </returns>
        public string Receive()
        {
            try
            {
                //int i;
                // 创建实例.
                StateObject state = new StateObject();
                state.workSocket = _Client;
                // 开始从远程设备接收数据
                _Client.BeginReceive(state.buffer, 0, StateObject.bufferSize, 0, new AsyncCallback(ReceiveCallback), state);

                //设置等待时间间隔
                //获取接收数据
                receiveDone.WaitOne(500);
                revData = state.sb.ToString();
                //返回接收到的数据
                return (revData);
            }
            catch (ObjectDisposedException oe)
            {
                if (OnError != null)
                    OnError(oe.Message, _Client, 0);
                return "";
            }
            catch (SocketException se)
            {
                if (OnError != null)
                    OnError(se.Message, _Client, 0);
                return "";
            }
            catch (Exception e)
            {
                //获得接收失败信息
                revInfo = e.ToString();
                //返回空字符串
                return ("");
            }
        }
        /// <summary>
        /// 数据接收返回函数
        /// </summary>
        /// <param name="ar">表示异步操作的状态</param>
        private static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                // 创建实例
                StateObject State = (StateObject)ar.AsyncState;
                Socket Client = State.workSocket;

                // 从远程设备读取数据
                int BytesRead = Client.EndReceive(ar);

                if (BytesRead > 0)
                {
                    // 可能有过多的数据,先存储缓冲区内的字符串
                    revTempString = Encoding.Default.GetString(State.buffer, 0, BytesRead);
                    //将缓冲区间的数据封装在一个StringBulid类型中
                    State.sb.Append(revTempString);
                    // 接收剩余数据
                    Client.BeginReceive(State.buffer, 0, StateObject.bufferSize, 0, new AsyncCallback(ReceiveCallback), State);
                }
                else
                {
                    // 所有数据都已经接收
                    if (State.sb.Length > 1)
                    {
                        string response = State.sb.ToString();
                    }
                    // 置位数据已接收标志位
                    receiveDone.Set();
                }
            }
            catch (ObjectDisposedException oe)
            {
                revInfo = oe.Message;
                throw oe;
            }
            catch (SocketException se)
            {
                revInfo = se.Message;
                throw se;
            }
            catch (Exception e)
            {
                // 获得接收失败信息
                revInfo = e.Message;
                throw e;
            }
        }
        #endregion

        #region 变量
        private static ManualResetEvent sendDone = new ManualResetEvent(false);
        private static ManualResetEvent connectDone = new ManualResetEvent(false);
        private static ManualResetEvent receiveDone = new ManualResetEvent(false);

        private static string connectInfo = "";
        private static string closeInfo = "";
        private static string sendInfo = "";
        private static string revInfo = "";
        private static string revData = "";
        private static string revTempString = "";

        private EndPoint _RemoteEP = null;
        private Socket _Client = null;

        public delegate void ErrorDelegate(string ErroMessage, Socket soc, int ErroCode);

        public event ErrorDelegate OnError;
        #endregion
    }

    public class StateObject
    {
        // Client   socket.
        public Socket workSocket = null;
        // Size of receive buffer.1024
        public const int bufferSize = 1024;
        // Receive buffer.
        public byte[] buffer = new byte[bufferSize];
        // Received data string.
        public StringBuilder sb = new StringBuilder();
    }
 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
一个服务器对多个客户端的MFC Socket编程示例(实现简单的即时通讯功能) 环境:Windows XP SP3、 VC++ 6.0、 Windows 2003 SDK 使用步骤: 1、下载解压之后,使用VC++ 6.0打开两个工程:一个是SocketServer和一个ClientSocket工程。 2、首先运行服务器端工程,选默认的端口1008 3、然后运行客户端工程,选默认的端口1008和默认的服务器地址 4、再运行多个客户端进程 5、如果一切正常,可以每个客户端的消息发送,我们可以在服务端和各个客户端同步看到消息 实现一个服务器对多个客户端的关键是,在服务端的使用集合CPtrList类用保存客户端的socket对象,思想与Java中的编程思想一样,只不过Java中会使用多线程技术,在Vector集合保存客户端的socket对象 ,而MFC框架提供了CSocket类,它是一个异步通信的类,所以看上去代码比较Java的多线程代码简单的实现了一个对多的即时通讯功能。另外,MFC提供了CSocketFile类和CArchive类与CSocket类实现了C++的网络通讯编程功能。 本示例注释非常详细,所有的辅助类都放一个util目录中,然后在工程中分了一个目录来管理这些辅助类,使用代码非常清晰。手动书写部分的代码是按Java的规范书写,当然其它代码由IDE生成的,所以是MS的风格,所以当你看代码时,只要是使用“骆驮命名法”的方法都是本人书写的功能性代码。 参看的思路:在服务端要从回调方法onAccept读起;而客户端代码主要从OnSendButton方法读起,即可理解整个代码的意思。 阅读对象:具有Java的Socket编程经验的人员,并且希望能够书写出比Java效率更高的即时通讯程序的人员

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值