- SuperSocket.ClientEngine版本:0.10.0.0,SuperSocket.ProtoBase版本:1.7.0.17
- 使用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(协议错误)错误。希望得到大神指点迷津,谢谢。