物理拓扑就不画了,是一般简单的CS架构
二,服务端实现过程
1), 服务端开始监听,并启动接收线程
public void Start(int port)
{
_listenPort = port;
serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
serverSocket.Bind(new IPEndPoint(IPAddress.Any, port));
serverSocket.Listen(_backlog);
Console.WriteLine("端口侦听开始");
for (int i = 0; i < _recieveThreadCount; i++)
{
Thread acceptThread = new Thread(new ThreadStart(RecieveAccept));
acceptThread.Name = "接收" + (i + 1) + "号线程";
acceptThreadList.Add(acceptThread);
acceptThread.Start();
}
}
2), 接收线程的实现,按照上面的逻辑图示,我们接收到连接后,就要实例连接对象,并注入监听对象的服务对象
Console.WriteLine(Thread.CurrentThread.Name + "开始");
while (true)
{
Socket clientSocket = serverSocket.Accept();
_clientSocketList.Add(new SocketClientBase(_instanceList, clientSocket));
Console.WriteLine(Thread.CurrentThread.Name + "获取到新的客户端(" + clientSocket.RemoteEndPoint.ToString() + ")");
}
服务端的代码就这么多,所有操作都是交给连接对象(SocketClientBase)去处理的
三,客户端实现过程(连接对象)
1), 服务对象定义
[Serializable()]
public class ObjectInstance
{
/// <summary>
/// 实例KEY
/// </summary>
public string InstanceKey { get; set; }
/// <summary>
/// 实例
/// </summary>
public object Instance { get; set; }
}
2), Request消息和Response消息的实现
[Serializable()]
abstract public class Message
{
abstract public MessageType MessageType { get; set; }
}
[Serializable()]
public class RequestMessage : Message
{
public RequestMessage(ActionType actionType, string instanceKey, string callName)
{
_requestKey = Guid.NewGuid().ToString();
ActionType = actionType;
InstanceKey = instanceKey;
CallName = callName;
}
private string _requestKey;
public string RequestKey
{
get { return _requestKey; }
private set { _requestKey = value; }
}
public DateTime SendTimeKey { get; set; }
public ActionType ActionType { get; private set; }
public string InstanceKey { get; private set; }
public string CallName { get; private set; }
public override MessageType MessageType
{
get
{
return Net.MessageType.Request;
}
set
{
throw new NotImplementedException();
}
}
public Object[] Parameters { get; set; }
}
[Serializable()]
public class ResponseMessage : Message
{
public ResponseMessage(string requestKey)
{
_requestKey = requestKey;
}
private string _requestKey;
public string RequestKey
{
get { return _requestKey; }
private set { _requestKey = value; }
}
public bool IsError { get; set; }
public XQException ErrorInfo { get; set; }
public object ReturnObject { get; set; }
public DateTime SendTimeKey { get; set; }
public override MessageType MessageType
{
get
{
return Net.MessageType.Response;
}
set
{
throw new NotImplementedException();
}
}
}
[Serializable()]
public enum ActionType
{
CallMethod = 0, CallProperty = 1, CallField = 4, Other = 8
}
[Serializable()]
public enum MessageType
{
Response = 0, Request = 1
}
上面我定义远程调用的方式的,和调用的约定对象,以及返回结果的定义
3),发送远程调用消息
/// <summary>
/// 调用远程方法
/// </summary>
/// <param name="instanceKey"></param>
/// <param name="methodName"></param>
/// <param name="pars"></param>
/// <returns></returns>
public ResponseMessage CallRemoteMethod(string instanceKey, string methodName, params object[] pars)
{
var response = new RequestMessage(ActionType.CallMethod, instanceKey, methodName);
if (pars != null && pars.Length > 0)
response.Parameters = pars;
return CallRemoteHost(response);
}
/// <summary>
/// 请求远程主机
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public ResponseMessage CallRemoteHost(RequestMessage request)
{
ResponseMessage response = null;
var getResponse = new OnGetReponseHandler(delegate(ResponseMessage args)
{
if (args.RequestKey == request.RequestKey)
{
response = args;
}
});
this.OnGetReponseEvent += getResponse;
SendRequest(request);
DateTime beginTime = DateTime.Now;
while (true)
{
if (TimeSpan.FromTicks(DateTime.Now.Ticks - beginTime.Ticks).TotalMilliseconds > 60 * 1000)
{
this.OnGetReponseEvent -= getResponse;
return new ResponseMessage(request.RequestKey) { IsError = true, ErrorInfo = XQException.GetException(5565, "远程操作超时") };
}
if (response != null)
break;
}
this.OnGetReponseEvent -= getResponse;
return response;
}
/// <summary>
/// 发送请求
/// </summary>
/// <param name="request"></param>
private void SendRequest(RequestMessage request)
{
byte[] data = SerializationHelper.ToByte(request);
var streamData = SetStreamDataEnd(data);
int count = clientSocket.Send(streamData);
Console.WriteLine("发送数据到" + count + "字节数据到" + clientSocket.RemoteEndPoint.ToString());
}
4), 回复远程调用,这里有两种情况,一种是远程主机发送过来的请求,另一种是远程主机响应的请求的回发
a),消息为请求,我们就需要执行请求的内容,然后返回执行结果
private void ActionRequest(RequestMessage request)
{
ResponseMessage response = new ResponseMessage(request.RequestKey);
Object instance = GetInstance(request.InstanceKey);
if (instance == null)
{
response.IsError = true;
response.ErrorInfo = XQException.GetException(5566, "实例不存在");
}
else
{
string callName = request.CallName;
switch (request.ActionType)
{
case ActionType.CallMethod:
var methodInfo = instance.GetType().GetMethod(callName);
if (methodInfo == null)
{
response.IsError = true;
response.ErrorInfo = XQException.GetException(5567, "方法不存在");
}
else
{
object result = methodInfo.Invoke(instance, request.Parameters);
response.ReturnObject = result;
}
break;
case ActionType.CallProperty:
var propertyInfo = instance.GetType().GetProperty(callName);
if (propertyInfo == null)
{
response.IsError = true;
response.ErrorInfo = XQException.GetException(5568, "属性不存在");
}
else
{
object result = propertyInfo.GetValue(instance, null);
response.ReturnObject = result;
}
break;
case ActionType.CallField:
var fieldInfo = instance.GetType().GetField(callName);
if (fieldInfo == null)
{
response.IsError = true;
response.ErrorInfo = XQException.GetException(5569, "字段不存在");
}
else
{
object result = fieldInfo.GetValue(instance);
response.ReturnObject = result;
}
break;
}
}
SendResponse(response);
}
b),当消息为返回的请求结果
private void ActionResponse(ResponseMessage response)
{
if (OnGetReponseEvent != null)
OnGetReponseEvent(response);
}
测试代码
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
//Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
//Application.Run(new Form1());
var serverInstance = new List<ObjectInstance>();
serverInstance.Add(new ObjectInstance() { InstanceKey = "Server-1", Instance = new Server() });
SocketServerBase sbServer = new SocketServerBase(serverInstance);
sbServer.Start(9999);
var clientInstance = new List<ObjectInstance>();
clientInstance.Add(new ObjectInstance() { InstanceKey = "client-1", Instance = new Client() });
SocketClientBase sbClient = new SocketClientBase(clientInstance);
sbClient.Connect(8888, "127.0.0.1", 9999);
Thread.Sleep(1000);
var client = sbServer.ClientSocketList.Find(p => p.RemoteIp == "127.0.0.1" && p.RemorePort == 8888);
StringBuilder sendText = new StringBuilder();
for (int i = 0; i < 10; i++)
{
sendText.Append(text);
}
string strText = sendText.ToString();
sendText.Length = 0;
while (true)
{
var response = sbClient.CallRemoteMethod("Server-1", "Add");
response = sbClient.CallRemoteMethod("Server-1", "Add2", 1, 2);
response = sbClient.CallRemoteMethod("Server-1", "Add3", 1, 2);
response = sbClient.CallRemoteMethod("Server-1", "Add4", strText);
client.CallRemoteMethod("client-1", "Print", strText);
}
Console.ReadLine();
}
public class Server
{
public void Add()
{
Console.WriteLine("Server Add");
}
public void Add2(int x, int y)
{
Console.WriteLine("Server Add2");
}
public int Add3(int x, int y)
{
Console.WriteLine("Server Add3");
return 1;
}
public int Add4(string text)
{
Console.WriteLine("Server Add3");
return 1;
}
}
public class Client
{
public void Print(string text)
{
// Console.WriteLine(text);
Console.WriteLine("Client Print");
}
}
总结,这个实现模型,是基于一种旁注理念的,松耦合的实现方式,这个模型只是一个原型,没有错误处理等其他一些外围实现,我试验过单客户端IO性能大概48M,由于没有设计线程池,所以只能小规模应用
转载请注明:http://www.cnblogs.com/Rolends
HAPPY EVERY DAY ! !