SuperSocket客户端与服务器端断开连接后,客户端重新连接服务端时会出现ClientClose和ProtocolError错误,而自动断开

  1. SuperSocket.ClientEngine版本:0.10.0.0,SuperSocket.ProtoBase版本:1.7.0.17
  2. 使用EasyClient连接服务器:
    定义了一个类来使用EasyClient
    ISocketClient.cs
using SuperSocket.ClientEngine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;

namespace WindowsClient
{
    public class ISocketClient
    {

        private EasyClient mClient;
        private SocketAsyncEventArgs recvEventArg = null;
        //接收数据事件
        public   Action<string> recvMessageEvent = null;
        //接受缓存数组
        private byte[] recvBuff = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        public ISocketClient()
        {
            mClient = new EasyClient();

            // Initialize the client with the receive filter and request handler
            mClient.Initialize(new ReceiveFilter(), (request) =>
            {
                // handle the received request
                Console.WriteLine(request.Key);
            });

            recvBuff = new byte[1024];
            recvEventArg = new SocketAsyncEventArgs();
            recvEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed);
            recvEventArg.SetBuffer(recvBuff, 0, 1024);

             连接断开事件
            mClient.Closed += ClientClosed; 
             收到服务器数据事件
            // += ClientDataReceived;
             连接到服务器事件
            //mClient.Socket
            mClient.Connected += ClientConnected;
             发生错误的处理
            mClient.Error += ClientError;

        }

        void ClientError(object sender, ErrorEventArgs e)
        {
            Console.WriteLine(e.Exception.Message);
        }

        void ClientConnected(object sender, EventArgs e)
        {
            Console.WriteLine("连接成功");
        }

        void ClientDataReceived(object sender, DataEventArgs e)
        {
            string msg = Encoding.Default.GetString(e.Data);
            Console.WriteLine(msg);
        }

        void ClientClosed(object sender, EventArgs e)
        {
            Console.WriteLine("连接断开");
        }
        /// <summary>
        /// 连接到服务器
        /// </summary>
        /// <param name="strIP">IP地址</param>
        /// <param name="iPort">端口</param>
        /// <returns>连接成功返回真</returns>
        public bool Connect(string strIP, int iPort)
        {
            // Connect to the server
            var rst = mClient.ConnectAsync(new IPEndPoint(IPAddress.Parse(strIP), iPort));

            if (rst.Result)
            {
                StartRecv();
                return true;

            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// tcp客户端开始接受tcp服务器发送的数据
        /// </summary>
        private void StartRecv()
        {
            bool willRaiseEvent = mClient.Socket.ReceiveAsync(recvEventArg);
            if (!willRaiseEvent)
            {
                ProcessReceive(recvEventArg);
            }
        }
        /// <summary>
        /// 处理接受到的tcp服务器数据
        /// </summary>
        /// <param name="e"></param>
        private void ProcessReceive(SocketAsyncEventArgs e)
        {
            AsyncUserToken token = (AsyncUserToken)e.UserToken;
            if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
            {
                if (recvMessageEvent != null)
                    //一定要指定GetString的长度,否则整个bugger都要转成string
                    recvMessageEvent(Encoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred));

                StartRecv();
            }
            else
            {
                //Restart();
            }
        }
        /// <summary>
        /// socket.sendAsync和socket.recvAsync的完成回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void IO_Completed(object sender, SocketAsyncEventArgs e)
        {
            switch (e.LastOperation)
            {
                case SocketAsyncOperation.Receive:
                    ProcessReceive(e);
                    break;
                case SocketAsyncOperation.Send:
                    //ProcessSend(e);
                    break;
                default:
                    throw new ArgumentException("The last operation completed on the socket was not a receive or send");
            }
        }
        /// <summary>
        /// 连接到服务器
        /// </summary>
        /// <param name="strIP">IP地址</param>
        /// <param name="strPort">端口</param>
        /// <returns>连接成功返回真</returns>
        public bool Connect(string strIP, string strPort)
        {
            int iPort = Convert.ToInt32(strPort);
            return Connect(strIP, iPort);
        }
        /// <summary>
        /// 是否连接
        /// </summary>
        /// <returns>true表示连接</returns>
        public bool IsConnected()
        {
            return mClient.IsConnected;
        }


        /// <summary>
        /// 向服务器发命令行协议的数据
        /// </summary>
        /// <param name="key">命令名称</param>
        /// <param name="data">数据</param>
        public void SendCommand(string key, string data)
        {
            if (mClient.IsConnected)
            {
                byte[] arrBytes = Encoding.Default.GetBytes(string.Format("{0} {1}", key, data));
                // Send data to the server
                mClient.Send(arrBytes);
            }
            else
            {
                throw new InvalidOperationException("断开连接");
            }
        }
        
    }
}

在服务中使用该类,并建立断开重连机制
Server.cs

            bool ConnStatus = false;
            while (true)
            {
                if (!ConnStatus)
                {
                    _client = new WindowsClient.ISocketClient();
                    _client = new WindowsClient.ISocketClient();
                    _client.recvMessageEvent += new Action<string>(Recv);
                    _client.Connect(ip, port);
                    var msg = $"{{\"Name\":\"{_ConConfig.Name}\",\"Password\":\"{_ConConfig.Password}\",\"SystemType\":\"WINDOWS\"}}\r\n";
                    //传递登录信息
                    _client.SendCommand("CONNECT", msg);
                    ConnStatus = true;
                }
                ConnStatus=_client.IsConnected(); //每次循环,获取连接状态,若false,则重新开始连接,若true则进行下一次循环。
                Thread.Sleep(500);
                
            }

由于在该版本的EasyClient中,未找到Recive事件,故使用了mClient对象中的Socket对象建立直接的接收消息方法。首次连接并不会有问题。当服务器主动关闭服务,再重新连接服务端时,服务器分别接收到:进入、登录(接收到消息)、退出:ClientClosing错误。于是在Server.cs中的循环会继续请求重新连接服务端。会重复上述步骤多次后,不再退出。但是当服务端一开始可以连接时,首次启动客户端,不会出现此错误。
3. 使用AsyncTcpSession,将如上代码中的EasyClient替换。该对象有Recive事件,进行注册。重新进行测试,会出现ProtocolError(协议错误)错误。希望得到大神指点迷津,谢谢。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值