[转]在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(二)

一.TcpSvr的使用方法
  A.测试程序:
using System;
  
using Ibms.Net.TcpCSFramework;
  
using System.Collections;
  
using System.Net.Sockets;
  
namespace Ibms.Test
  {
  
/// <summary>
  
/// 测试TcpSvr的类
  
/// </summary>
  public class TestTcpSvr
  {
   
   
public TestTcpSvr()
   {
   
   }
   
   
public static void Main()
   {
   
try
   {
   Console.WriteLine(
"Begin to Test TcpSvr class");
   TestTcpSvr tts 
= new TestTcpSvr();
   
//TcpSvr svr = new TcpSvr(9050,4);//默认使用Encoding.Default编码方式
   TcpSvr svr = new TcpSvr(9050,4,new Coder(Coder.EncodingMothord.UTF8));
   svr.Resovlver 
= new DatagramResolver("##");
   
//定义服务器的4个事件
   
//服务器满
   svr.ServerFull += new NetEvent(tts.ServerFull);
   
//新客户端连接
   svr.ClientConn += new NetEvent(tts.ClientConn);
   
//客户端关闭
   svr.ClientClose += new NetEvent(tts.ClientClose);
   
//接收到数据
   svr.RecvData += new NetEvent(tts.RecvData);
   
   
//命令控制循环
   while(true)
   {
   Console.Write(
">");
   
string cmd=Console.ReadLine();
   
//退出测试程序
   if(cmd.ToLower() == "exit")
   {
   
break;
   }
   
//停止服务器程序
   if(cmd.ToLower() == "stop")
   {
   svr.Stop();
   
   Console.WriteLine(
"Server is Stop.");
   
continue;
   }
   
//运行服务器程序
   if(cmd.ToLower() == "start")
   {
   svr.Start();
   Console.WriteLine(
"Server is listen{0}",
   svr.ServerSocket.LocalEndPoint.ToString());
   
continue;
   }
   
//察看服务器在线客户端数目和容量
   if(cmd.ToLower() == "count")
   {
   Console.WriteLine(
"Current count of Client is {0}/{1}",
   svr.SessionCount,svr.Capacity);
   
continue;
   }
   
//发送数据到客户端格式:send [Session] [stringData]
   if(cmd.ToLower().IndexOf("send"!=-1)
   {
   cmd 
= cmd.ToLower();
   
string[] para = cmd.Split(' ');
   
if(para.Length ==3)
   {
   
   Session client 
= (Session)svr.SessionTable[ new SessionId( int.Parse
   (para[
1]))];
   
if(client !=null)
   {
   svr.Send(client, para[
2]);
   }
   
else
   {
   Console.WriteLine(
"The Session is Null");
   }
   
   }
   
else
   {
   Console.WriteLine(
"Error Command");
   }
   
continue;
   }
   
//从服务器上踢掉一个客户端
   if(cmd.ToLower().IndexOf("kick"!=-1)
   {
   cmd 
= cmd.ToLower();
   
string[] para = cmd.Split(' ');
   
   
if(para.Length ==2)
   {
   Session client 
= (Session)svr.SessionTable[ new SessionId( int.Parse
   (para[
1]))];
   
if(client !=null)
   {
   svr.CloseSession(client);
   }
   
else
   {
   Console.WriteLine(
"The Session is Null");
   }
   }
   
else
   {
   Console.WriteLine(
"Error command");
   }
   
   
continue;
   }
   
//列出服务器上所有的客户端信息
   if(cmd.ToLower() == "list")
   {
   
int i=0
   
foreach( Session Client in svr.SessionTable.Values)
   {
   
if(Client !=null)
   {
   i
++;
   
string info = string.Format("{0} Client:{1} connected server Session:{2}. Socket Handle:{3}",
   i,
   Client.ClientSocket.RemoteEndPoint.ToString(),
   Client.ID,
   Client.ClientSocket.Handle);
   Console.WriteLine( info );
   }
   
else
   {
   i
++;
   
string info = string.Format("{0} null Client", i);
   Console.WriteLine(info);
   }
   }
   
continue;
   
   }
   Console.WriteLine(
"Unkown Command");
   }
//end of while
   Console.WriteLine("End service");
   }
   
catch(Exception ex)
   {
   Console.WriteLine(ex.ToString());
   }
   }
   
void ClientConn(object sender, NetEventArgs e)
   {
   
string info = string.Format("A Client:{0} connect server Session:{1}. Socket Handle:{2}",
   e.Client.ClientSocket.RemoteEndPoint.ToString(),
   e.Client.ID,e.Client.ClientSocket.Handle);
   Console.WriteLine( info );
   Console.Write(
">");
   }
   
   
void ServerFull(object sender, NetEventArgs e)
   {
   
string info = string.Format("Server is full.the Client:{0} is refused",
   e.Client.ClientSocket.RemoteEndPoint.ToString());
   
//Must do it
   
//服务器满了,必须关闭新来的客户端连接
   e.Client.Close();
   Console.WriteLine(info);
   Console.Write(
">");
   }
   
void ClientClose(object sender, NetEventArgs e)
   {
   
string info ;
   
if( e.Client.TypeOfExit == Session.ExitType.ExceptionExit)
   {
   info
= string.Format("A Client Session:{0} Exception Closed.",
   e.Client.ID);
   }
   
else
   {
   info
= string.Format("A Client Session:{0} Normal Closed.",
   e.Client.ID);
   }
   Console.WriteLine( info );
   Console.Write(
">");
   }
   
void RecvData(object sender, NetEventArgs e)
   {
   
string info = string.Format("recv data:{0} from:{1}.",e.Client.Datagram, e.Client);
   Console.WriteLine( info );
   TcpSvr svr 
= (TcpSvr) sender;
   
//测试把收到的数据返回给客户端
   svr.Send(e.Client, e.Client.Datagram);
   Console.Write(
">");
   
   }
  }
  }
B.说明:
  使用命令来操作服务器
  exit 退出
  start 开始服务
  kick 关闭客户端
  send 发送数据
  list 列出所有客户端的状态
  count 客户端计数
  先启动服务运行start,等待客户端连接。
  然后可以使用list,count察看当前的连接状况
  每个事件都有相应函数,客户就在事件处理函数中处理自己的业务逻辑
  可以通过继承特化自己的服务器应用,基本的框架不变
  二.TcpCli的使用方法
  A.测试程序:
using System;
  
using Ibms.Net.TcpCSFramework;
  
namespace Ibms.Test
  {
  
/// <summary>
  
/// TestTcpClient 的摘要说明。
  
/// </summary>
  public class TestTcpClient
  {
   
public TestTcpClient()
   {
   
//
   
// TODO: 在此处添加构造函数逻辑
   
//
   }
   
public static void Test()
   {
   Console.WriteLine(
"Begin to Test TcpCli Class..");
   TestTcpClient test 
= new TestTcpClient();
   TcpCli cli 
= new TcpCli( new Coder(Coder.EncodingMothord.UTF8));
   cli.Resovlver 
= new DatagramResolver("##");
   cli.ReceivedDatagram 
+= new NetEvent(test.RecvData);
   cli.DisConnectedServer 
+= new NetEvent(test.ClientClose);
   cli.ConnectedServer 
+= new NetEvent(test.ClientConn);
   
   
try
   {
   
//命令控制循环
   while(true)
   {
   Console.Write(
">");
   
string cmd=Console.ReadLine();
   
if(cmd.ToLower() == "exit")
   {
   
break;
   }
   
if(cmd.ToLower() == "close")
   {
   cli.Close();
   
   
continue;
   }
   
if(cmd.ToLower().IndexOf("conn")!=-1)
   {
   cmd 
= cmd.ToLower();
   
string[] para = cmd.Split(' ');
   
if(para.Length ==3)
   {
   
   cli.Connect(para[
1],int.Parse(para[2]));
   }
   
else
   {
   Console.WriteLine(
"Error Command");
   }
   
continue;
   }
   
if(cmd.ToLower().IndexOf("send"!=-1)
   {
   
   
   cmd 
= cmd.ToLower();
   
string[] para = cmd.Split(' ');
   
if(para.Length ==2)
   {
   
   cli.Send(para[
1]);
   
   }
   
else
   {
   Console.WriteLine(
"Error Command");
   }
   
continue;
   }
   
   Console.WriteLine(
"Unkown Command");
   }
//end of while
   Console.WriteLine("End service");
   }
   
catch(Exception ex)
   {
   Console.WriteLine(ex.ToString());
   }
   }
   
void ClientConn(object sender, NetEventArgs e)
   {
   
string info = string.Format("A Client:{0} connect server :{1}",e.Client,
   e.Client.ClientSocket.RemoteEndPoint.ToString());
   Console.WriteLine( info );
   Console.Write(
">");
   }
   
   
void ClientClose(object sender, NetEventArgs e)
   {
   
string info ;
   
if( e.Client.TypeOfExit == Session.ExitType.ExceptionExit)
   {
   info
= string.Format("A Client Session:{0} Exception Closed.",
   e.Client.ID);
   }
   
else
   {
   info
= string.Format("A Client Session:{0} Normal Closed.",
   e.Client.ID);
   }
   Console.WriteLine( info );
   Console.Write(
">");
   }
   
void RecvData(object sender, NetEventArgs e)
   {
   
string info = string.Format("recv data:{0} from:{1}.",e.Client.Datagram, e.Client);
   Console.WriteLine( info );
   
   Console.Write(
">");
   
   }
  }
  }

B.说明:
先建立连接,Conn 192.9.207.214 9050
然后可以Send 数据
最后关闭连接Close
三.编码器
如果你要加密你的报文,需要一个你自己的Coder
从Coder类继承一个如MyCoder类,然后重载编码和解码函数。
使用方法:
TcpCli cli = new TcpCli( new MyCoder());
就可以在客户端使用该编码器了。
四.报文解析器
与编码器同样的实现方法。

posted @ 2009-10-15 09:15  虾吵吵  阅读(894)  评论(0编辑  收藏  举报