上一节我们讲了即时通信程序的服务端的搭建,今天我们来实现客户端的登录。
就像我们qq登录一样都需要一个唯一的qq号,当然qq号是长久使用的,而我们的这个即时通信程序只是临时的聊天使用,为了区别不同的用户,我们需要用户在使用该程序时注册一个用户名,然后要向固定的IP+端口发送请求,连接服务器。先上个图,然后再开始讲解!
上边已经说了,在登录的时候都需要用户起一个用户名,这个用户名用户当然可以随意起,然后登录,连接服务器,这个时候需要服务器注意的是用户名重名的问题,我们还记得我们在搭建服务器端的时候建立了一个Dictionary<string,Socket>字典onlineListServer来保存负责和客户端通信的套接字,也就是Dictionary的键也是唯一的,所以这个用户名必须是唯一的,用户是随机输入的,当然可能有重名的问题,如果有重名,这个时候我们需要在服务端和登录端做双重的处理,在服务端,上一节我们已经讲了,在用户连接成功之后先判断onlineListServer字典中是否存在与用户名相同的键,如果存在则将用户名+"1",并将与之负责的通信套接字加入该字典中,并向登录端发送一个消息告诉登录端,该用户名已存在,要用户端做好重名处理,用户端接受服务端发送的消息,根据消息内容的不同做不同的处理,如果重名,则和客户端一样将用户名+“1”,如果不重名,则直接登录成功,进行客户端主界面。
下面我会通过具体的代码跟大家慢慢的解释。
首先创建一个Form窗体,命名为ClientLogin,界面布局如上,主要控件如下:
三个文本框,分别为txtIP,txtPort,txtName,分别代表请求服务端IP和端口,登录 用户名
两个按钮,分别为btndl,btnqx分别表示登录和取消。
因为我们需要记录登录名,然后根据不同的登录名来进行区别不同的用户,同时每一个登录名对应一个相应的TCPClient对象来连接、监听客户端并且和其他对象进行通信。所以我们需要为该ClientLogin添加额外的属性分别是string类型的LoginName和TcpClient类型的TCPClient,分别表示用户登录名和负责连接通信的TCPClient实例。
代码如下:
在 public partial class ClientLogin : Form
{}中添加属性:
public string LoginName //登录名 { get ; set ; } public TcpClient TCPClient //连接通信实例 { get ; set ; } |
在btndl按钮的Click事件的处理函数中写下如下代码
private void btndl_Click( object sender, EventArgs e) { if (! string .IsNullOrEmpty(txtIP.Text.ToString())) //判断IP是否为空,请求、监听服务端IP { if (! string .IsNullOrEmpty(txtName.Text.Trim())) //判断用户名是否为空,请求服务端固定端口 { this .LoginName = txtName.Text; try { this .TCPClient = new TcpClient(); //示例化ClientLogin.TCPClient属性 this .TCPClient.Connect(IPAddress.Parse(txtIP.Text), Convert.ToInt32(txtPort.Text)); //连接服务器 netStream = TCPClient.GetStream();示例化 byte [] buffer = Encoding.Default.GetBytes( "ON|" + LoginName + "|" ); netStream.Write(buffer,0,buffer.Length); //向服务器发送登录者名,并等待服务端的验证 Thread.Sleep(100); byte [] buffer1= new byte [1]; netStream.Read(buffer1, 0, 1); //获取服务端回发的验证消息 string i = Encoding.Default.GetString(buffer1); //根据不同的消息做不同的处理 if (i== "1" ) //如果为“1”则表示用户名重名,需做重名处理 { this .LoginName += "1" ; } this .DialogResult = DialogResult.OK; this .Close(); } catch (Exception e1) { MessageBox.Show( "连接异常:" + e1.Message); } } else { MessageBox.Show( "请输入登陆昵称!" ); } } else { MessageBox.Show( "请确保输入一个有效的IP地址!" ); } } |
在取消按钮中做如下处理:
private void btntc_Click( object sender, EventArgs e) { this .DialogResult = DialogResult.No; this .Close(); } |
这个时候关于即时通信程序的登录端已经做好了,但是现在请大家考虑这样的一个问题,我们的登录界面只是起一个登录连接的作用,在登录成功以后我们直接就进入了聊天界面,这个登录界面就没有任何意义了,如何把该登录界面给消除了,有人会说直接this.IsVisialbe=fales,隐藏不得了,但是这样的话即使聊天客户端关闭以后,程序仍在运行,因为主程序并没有被关闭。也许还有的朋友会说,直接this.close();,但是这样的话整个应用程序就被关闭了,因为我们在Program.cs里启用的主程序为ClientLogin界面,该界面一关闭,该程序也就关闭了。那么我们该如何做呢?
这个时候我们需要在Program.cs文件里边做如下的修改:
static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault( false ); ClientLogin clientLogin = new ClientLogin(); if (clientLogin.ShowDialog() == DialogResult.OK) { Application.Run( new ChatClient(clientLogin)); } else { Application.Exit(); } } |
在应用程序的主函数里,我们先实例化一个ClientLogin对象,即程序运行时先弹出登陆页面,然后再根据登陆界面clientLogin.ShowDialog()的结果进行判断,如果登陆成功即:DialogResult.OK则这个时候程序才开始运行聊天主客户端,如果DialogResult不是OK,则这个时候聊天主客户端根本就不会运行。现在大家明白了为什么在ClientLogin.cs页会有四行代码作高亮标注了吧,他们就是为给ClientLogin的Dialogresult属性赋值,根据登录情况的不同,赋不同的值,进而控制聊天主客户端是否运行。在这里如果我们关闭了聊天主客户端,我们的程序马上就会关闭,因为我们的运行的主程序即为聊天主客户端,而非登录端。如果大家对这一点还有不明白的可以参看我之前的博文《C# 关闭登录窗体,进入主窗体后,主窗体关闭,程序进程仍在运行的问题》。
好了,这一节就到这里了,在这一节里我们实现了即时通信程序客户端的登录,在这里需要注意的是客户端登录时重名问题,以及登录成功后登录窗体的关闭问题。希望可以对大家有所帮助,也希望大家多多指点。我会在下一节给教授大家如何实现即时通信程序的主客户端也就是聊天这一块。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构