C#编写简单的聊天程序

本文介绍了如何使用C#编写一个简单的聊天程序,包括程序的分析与设计、网络编程基础、接口设计以及代码实现。在分析设计阶段,通过与客户的沟通明确需求,编写用例,定义消息结构、消息发送方和接收方的接口。在实现过程中,创建了`IMessageSender`和`IMessageReceiver`接口,并分别实现发送和接收消息的功能。此外,还设计了主程序`Talker`,它结合了发送和接收的实现。文章最后提供了窗体设计和事件代码的示例,展示了如何通过事件驱动机制处理聊天过程中的各种交互。
摘要由CSDN通过智能技术生成

引言

这是一篇基于Socket进行网络编程的入门文章,我对于网络编程的学习并不够深入,这篇文章是对于自己知识的一个巩固,同时希望能为初学的朋友提供一点参考。文章大体分为四个部分:程序的分析与设计、C#网络编程基础(篇外篇)、聊天程序的实现模式、程序实现。

程序的分析与设计

1.明确程序功能

如果大家现在已经参加了工作,你的经理或者老板告诉你,“小王,我需要你开发一个聊天程序”。那么接下来该怎么做呢?你是不是在脑子里有个雏形,然后就直接打开VS2005开始设计窗体,编写代码了呢?在开始之前,我们首先需要进行软件的分析与设计。就拿本例来说,如果只有这么一句话“一个聊天程序”,恐怕现在大家对这个“聊天程序”的概念就很模糊,它可以是像QQ那样的非常复杂的一个程序,也可以是很简单的聊天程序;它可能只有在对方在线的时候才可以进行聊天,也可能进行留言;它可能每次将消息只能发往一个人,也可能允许发往多个人。它还可能有一些高级功能,比如向对方传送文件等。所以我们首先需要进行分析,而不是一上手就开始做,而分析的第一步,就是搞清楚程序的功能是什么,它能够做些什么。在这一步,我们的任务是了解程序需要做什么,而不是如何去做。

了解程序需要做什么,我们可以从两方面入手,接下来我们分别讨论。

1.1请求客户提供更详细信息

我们可以做的第一件事就是请求客户提供更加详细的信息。尽管你的经理或老板是你的上司,但在这个例子中,他就是你的客户(当然通常情况下,客户是公司外部委托公司开发软件的人或单位)。当遇到上面这种情况,我们只有少得可怜的一条信息“一个聊天程序”,首先可以做的,就是请求客户提供更加确切的信息。比如,你问经理“对这个程序的功能能不能提供一些更具体的信息?”。他可能会像这样回答:“哦,很简单,可以登录聊天程序,登录的时候能够通知其他在线用户,然后与在线的用户进行对话,如果不想对话了,就注销或者直接关闭,就这些吧。”

有了上面这段话,我们就又可以得出下面几个需求:

  1. 程序可以进行登录。
  2. 登录后可以通知其他在线用户。
  3. 可以与其他用户进行对话。
  4. 可以注销或者关闭。
1.2对于用户需求进行提问,并进行总结

经常会有这样的情况:可能客户给出的需求仍然不够细致,或者客户自己本身对于需求就很模糊,此时我们需要做的就是针对用户上面给出的信息进行提问。接下来我就看看如何对上面的需求进行提问,我们至少可以向经理提出以下问题:

NOTE:这里我穿插一个我在见到的一个印象比较深刻的例子:客户往往向你表达了强烈的意愿他多么多么想拥有一个属于自己的网站,但是,他却没有告诉你网站都有哪些内容、栏目,可以做什么。而作为开发者,我们显然关心的是后者。

  1. 登录时需要提供哪些内容?需不需要提供密码?
  2. 允许多少人同时在线聊天?
  3. 与在线用户聊天时,可以将一条消息发给一个用户,还是可以一次将消息发给多个用户?
  4. 聊天时发送的消息包括哪些内容?
  5. 注销和关闭有什么区别?
  6. 注销和关闭对对方需不需要给对方提示?

由于这是一个范例程序,而我在为大家讲述,所以我只能再充当一下客户的角色,来回答上面的问题:

  1. 登录时只需要提供用户名称就可以了,不需要输入密码。
  2. 允许两个人在线聊天。(这里我们只讲述这种简单情况,允许多人聊天需要使用多线程)
  3. 因为只有两个人,那么自然是只能发给一个用户了。
  4. 聊天发送的消息包括:用户名称、发送时间还有正文。
  5. 注销并不关闭程序,只是离开了对话,可以再次进行连接。关闭则是退出整个应用程序。
  6. 注销和关闭均需要给对方提示。

好了,有了上面这些信息我们基本上就掌握了程序需要完成的功能,那么接下来做什么?开始编码了么?上面的这些属于业务流程,除非你对它已经非常熟悉,或者程序非常的小,那么可以对它进行编码,但是实际中,我们最好再编写一些用例,这样会使程序的流程更加的清楚。

1.3编写用例

通常一个用例对应一个功能或者叫需求,它是程序的一个执行路径或者执行流程。编写用例的思路是:假设你已经有了这样一个聊天程序,那么你应该如何使用它?我们的使用步骤,就是一个用例。用例的特点就每次只针对程序的一个功能编写,最后根据用例编写代码,最终完成程序的开发。我们这里的需求只有简单的几个:登录,发送消息,接收消息,注销或关闭,上面的分析是对这几点功能的一个明确。接下来我们首先编写第一个用例:登录。

在开始之前,我们先明确一个概念:客户端,服务端。因为这个程序只是在两个人(机器)之间聊天,那么我们大致可以绘出这样一个图来:

我们期望用户A和用户B进行对话,那么我们就需要在它们之间建立起连接。尽管“用户A”和“用户B”的地位是对等的,但按照约定俗称的说法:我们将发起连接请求的一方称为客户端(或叫本地),另一端称为服务端(或叫远程)。所以我们的登录过程,就是“用户A”连接到“用户B”的过程,或者说客户端(本地)连接到服务端(远程)的过程。在分析这个程序的过程中,我们总是将其分为两部分,一部分为发起连接、发送消息的一方(本地),一方为接受连接、接收消息的一方(远程)。

登录和连接(本地)
主路径 可选路径
1.打开应用程序,显示登录窗口  
2.输入用户名  
3.点击“登录”按钮,登录成功 3.“登录”失败

如果用户名为空,重新进入第2步。

4.显示主窗口,显示登录的用户名称  
5.点击“连接”,连接至远程  
6.连接成功
6.1提示用户,连接已经成功。
6.连接失败
6.1 提示用户,连接不成功
5.在用户界面变更控件状态

5.2连接为灰色,表示已经连接

5.3注销为亮色,表示可以注销

5.4发送为亮色,表示可以发消息

 

这里我们的用例名称为登录和连接,但是后面我们又打了一个括号,写着“本地”,它的意思是说,登录和连接是客户端,也就是发起连接的一方采取的动作。同样,我们需要写下当客户端连接至服务端时,服务端采取的动作。

登录和连接(远程)
主路径 可选路径
1-4 同客户端  
5.等待连接  
6.如果有连接,自动在用户界面显示“远程主机连接成功”  

接下来我们来看发送消息。在发送消息时,已经是登录了的,也就是“用户A”、“用户B”已经做好了连接,所以我们现在就可以只关注发送这一过程:

发送消息(本地)
主路径 可选路径
1.输入消息  
2.点击发送按钮 2.没有输入消息,重新回到第1步
3.在用户界面上显示发出的消息 3.服务端已经断开连接或者关闭

3.1在客户端用户界面上显示错误消息

然后我们看一下接收消息,此时我们只关心接收消息这一部分。

接收消息(远程)
主路径 可选路径
1.侦听到客户端发来的消息,自动显示在用户界面上。  

注意到这样一点:当远程主机向本地返回消息时,它的用例又变为了上面的用例“发送消息(本地)”。因为它们的角色已经互换了。

最后看一下注销,我们这里研究的是当我们在本地机器点击“注销”后,双方采取的动作:

注销(本地主动)
主路径 可选路径
1.点击注销按钮,断开与远程的连接  
2.在用户界面显示已经注销  
3.更改控件状态

3.1注销为灰色,表示已经注销

3.2连接为亮色,表示可以连接

3.3发送为灰色,表示无法发送

 

与此对应,服务端应该作出反应:

注销(远程被动)
主路径 可选路径
1.自动显示远程用户已经断开连接。  

注意到一点:当远程主动注销时,它采取的动作为上面的“本地主动”,本地采取的动作则为这里的“远程被动”。

至此,应用程序的功能分析和用例编写就告一段落了,通过上面这些表格,之后再继续编写程序变得容易了许多。另外还需要记得,用例只能为你提供一个操作步骤的指导,在实现的过程中,因为技术等方面的原因,可能还会有少量的修改。如果修改量很大,可以重新修改用例;如果修改量不大,那么就可以直接编码。这是一个迭代的过程,也没有一定的标准,总之是以高效和合适为标准。

2.分析与设计

我们已经很清楚地知道了程序需要做些什么,尽管现在还不知道该如何去做。我们甚至可以编写出这个程序所需要的接口,以后编写代码的时候,我们只要去实现这些接口就可以了。这也符合面向接口编程的原则。另外我们注意到,尽管这是一个聊天程序,但是却可以明确地划分为两部分,一部分发送消息,一部分接收消息。另外注意上面标识为自动的语句,它们暗示这个操作需要通过事件的通知机制来完成。关于委托和事件,可以参考这两篇文章:

  • C#中的委托和事件 - 委托和事件的入门文章,同时捎带讲述了Observer设计模式和.NET的事件模型
  • C#中的委托和事件(续) - 委托和事件更深入的一些问题,包括异常、超时的处理,以及使用委托来异步调用方法。
2.1消息Message

首先我们可以定义消息,前面我们已经明确了消息包含三个部分:用户名、时间、内容,所以我们可以定义一个结构来表示这个消息:

public struct Message {
    private readonly string userName;
    private readonly string content;
    private readonly DateTime postDate;

   

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值