阅读文章

【C#食谱】【杭帮菜】菜单1:写一个TCP服务端 问题:

[日期:2008-04-23] 来源:  作者: [字体: ]

     你需要写一个服务端去监听从某一个端口进来的一个TCP客户端的请求。然后,这些请求可以在服务端被处理,并且每一个响应都可以被发送到TCP客户端。我将在下一个“菜”中介绍怎么样创建一个TCP客户端和服务端进行交互。
  
  解决方法:
  
  我们创建一个MyTcpServer的类来监听从一个端口进来的基于TCP终端的请求:
  
  class MyTcpServer
  {
  #region Private Members
  private TcpListener _listener = null;
  private IPAddress _address;
  private int _port;
  private bool _listening = false;
  #endregion
  
  #region 构造函数 public MyTcpServer(IPAddress address, int port)
  {
  _port = port;
  _address = address;
  }
  #endregion // 构造函数}这个MyTCPServer类有两个属性:
  
  Address(IPAddress)
  Port(int)
  下面这些返回当前服务端正在监听的地址和端口,并且返回监听的状态:
  
  #region Properties
  public IPAddress Address
  {
  get { return _address; }
  }
  
  public int Port
  {
  get { return _port; }
  }
  
  public bool Listening
  {
  get { return _listening; }
  }
  #endregion这个Listen方法告诉MyTcpServer类开始在某个地址和端口对上开始监听。你创建并启动了一个TcpListener,然后调用它的AcceptTcpClient方法去等待一个客户端请求的到来。一旦客户端连接成功,一个请求将被发送到线程池去处理客户端,它将运行ProcessClient方法。
  
  监听器将在处理完客户端的请求后关闭:
  
  
  
  public void Listen()
  {
  try
  {
  lock (_syncRoot)
  {
  _listener = new TcpListener(_address, _port);
  
  // 启动服务器
  _listener.Start();
  
  // 设置为监听状态
  _listening = true;
  }
  
  // 监听
  do
  {
  Trace.Write("Looking for someone to talk to…?");
  
  // 等待连接
  TcpClient newClient = _listener.AcceptTcpClient();
  Trace.WriteLine("Connected to new client");
  
  // 排队处理客户的请求
  ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessClient),
  newClient);
  }
  while (_listening);
  }
  catch (SocketException se)
  {
  Trace.WriteLine("SocketException: " + se.ToString());
  }
  finally
  {
  // 关闭
  StopListening();
  }
  }StopListening方法使得TCPServer停止监听请求:public void StopListening()
  {
  if (_listening)
  {
  lock (_syncRoot)
  {
  // 设置为非监听状态
  _listening = false;
  // 关闭
  _listener.Stop();
  }
  }
  }ProcessClient方法在一个线程池上被执行用来处理一个已经连接的客户端。它通过TcpClient.GetStream方法从客户端得到NetworkStream,然后读取整个请求。在返回一个响应后,它关闭客户端的连接。
  
  
  
  #region 私有方法
  private void ProcessClient(object client)
  {
  TcpClient newClient = (TcpClient)client;
  try
  {
  // 缓存读取的数据 byte[] bytes = new byte[1024];
  StringBuilder clientData = new StringBuilder();
  
  // 获取NetworkStream
  using (NetworkStream ns = newClient.GetStream())
  {
  
  // 初始化一个连接的read timeout为1分钟
  ns.ReadTimeout = 60000; int bytesRead = 0;
  do
  {
  // 读取数据
  try
  {
  bytesRead = ns.Read(bytes, 0, bytes.Length);
  if (bytesRead > 0)
  {
  // 把bytes数据转换成ASCII类型的字符串,并加到末尾
  clientData.Append(
  Encoding.ASCII.GetString(bytes, 0, bytesRead));
  // 减少read timeout到1秒
  ns.ReadTimeout = 1000;
  }
  }
  catch (IOException ioe)
  {
  // 读取超时;所有的数据都已经被读取了
  Trace.WriteLine("Read timed out: " + ioe.ToString());
  bytesRead = 0;
  }
  }
  while (bytesRead > 0);
  
  Trace.WriteLine("Client says: " + clientData.ToString());
  
  bytes = Encoding.ASCII.GetBytes("Thanks call again!");
  
  // 返回一个响应
  ns.Write(bytes, 0, bytes.Length);
  }
  }
  finally
  {
  // 关闭客户端的连接
  if(newClient != null)
  newClient.Close();
  }
  }
  #endregion一个简单的监听客户端的服务端程序是这样的:
  class Program
  {
  static MyTcpServer server = null;
  static void Main(string[] args)
  {
  // 在另一个线程上运行服务端
  ThreadPool.QueueUserWorkItem(RunServer);
  
  Console.WriteLine("Press Esc to stop the server…?");
  ConsoleKeyInfo cki;
  while(true)
  {
  
  cki = Console.ReadKey();
  if (cki.Key == ConsoleKey.Escape)
  break;
  }
  }
  
  static void RunServer( object stateInfo )
  {
  // 启动
  server = new MyTcpServer(IPAddress.Loopback,55555);
  server.Listen();
  }
  }具体的输出将在下一个配套的菜(写一个TCP客户端)中再发布出来。讨论:传输控制协议(TCP)是目前Internet上被广泛使用的协议。
  TCP协议是对从一个终端到另一个终端正确发生数据包负责的(有连接的)。
  它使用Internet协议(IP)去传输数据。IP从端到端的获取数据包;
  TCP检查数据包是否被正确地发送了,有没有丢包,有没有乱序;
  如果有,TCP会使丢失的或损害的包重新发送。
  TCPServer类是处理从基于TCP的客户端发送过来的请求的基本服务端机制。MyTcpServer类使用传进来的IP地址和端口号作为参数,
  并且在Listen方法中在该IP地址和端口上创建一个TcpListener。
  一旦创建成功,TcpListener.Start方法被调用来启动服务器
  这个阻塞的AcceptTcpClient方法被调用来监听来自基于TCP的客户端的请求。
  一旦建立连接,ProcessClient方法将执行。
  在这个方法中,服务器从客户端读取数据,并返回一个可信的响应。
  服务器通过NetworkStream.Close方法和TcpClient.Close方法来中断和客户端的连接。
  当StopListening方法被调用的时候,服务器停止监听。
  StopListening方法通过调用TcpListener.Stop方法来使服务器掉线。  


阅读:
录入:blue1000

评论 】 【 推荐 】 【 打印
上一篇:雕虫小技--授权控件
下一篇:坚持学习WF(6):开发可复用的宿主程序
相关文章      
本文评论
发表评论


点评: 字数
姓名:

  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款