分享一个C#编写简单的聊天程序(详细介绍)

2019-12-26 16:55:38刘景俊


public interface IMessageReceiver {
 event MessageReceivedEventHandler MessageReceived; // 接收到发来的消息
 event ConnectionLostEventHandler ClientLost;  // 远程主动断开连接
 event ClientConnectedEventHandler ClientConnected; // 远程连接到了本地
 void StartListen();  // 开始侦听端口
 void StopListen();  // 停止侦听端口
}

我记得曾经看过有篇文章说过,最好不要在接口中定义事件,但是我忘了他的理由了,所以本文还是将事件定义在了接口中。

2.4主程序Talker

而我们的主程序是既可以发送,又可以接收,一般来说,如果一个类像获得其他类的能力,以采用两种方法:继承和复合。因为C#中没有多重继承,所以我们无法同时继承实现了IMessageReceiver和IMessageSender的类。那么我们可以采用复合,将它们作为类成员包含在Talker内部:


public class Talker {
 private IMessageReceiver receiver;
 private IMessageSender sender;

 public Talker(IMessageReceiver receiver, IMessageSender sender) {
  this.receiver = receiver;
  this.sender = sender;
 }
 }

现在,我们的程序大体框架已经完成,接下来要关注的就是如何实现它,现在让我们由设计走入实现,看看实现一个网络聊天程序,我们需要掌握的技术吧。

C#网络编程基础(篇外篇)

这部分的内容请参考 C#网络编程 系列文章,共5个部分较为详细的讲述了基于Socket的网络编程的初步内容。

编写程序代码

如果你已经看完了上面一节C#网络编程,那么本章完全没有讲解的必要了,所以我只列出代码,对个别值得注意的地方稍微地讲述一下。首先需要了解的就是,我们采用的是三个模式中开发起来难度较大的一种,无服务器参与的模式。还有就是我们没有使用广播消息,所以需要提前知道连接到的远程主机的地址和端口号。

1.实现IMessageSender接口


public class MessageSender : IMessageSender {

 TcpClient client;
 Stream streamToServer;

 // 连接至远程
 public bool Connect(IPAddress ip, int port) {
  try {
  client = new TcpClient();
  client.Connect(ip, port);
  streamToServer = client.GetStream(); // 获取连接至远程的流
  return true;
  } catch {
  return false;
  }
 }

 // 发送消息
 public bool SendMessage(Message msg) {
  try {
  lock (streamToServer) {
   byte[] buffer = Encoding.Unicode.GetBytes(msg.ToString());
   streamToServer.Write(buffer, 0, buffer.Length);
   return true;
  }
  } catch {
  return false;
  }
 }

 // 注销
 public void SignOut() {
  if (streamToServer != null)
  streamToServer.Dispose();
  if (client != null)
  client.Close();
 }
 }