计算机网络课程设计之网络聊天程序的设计与实现 您所在的位置:网站首页 网页聊天程序的项目背景 计算机网络课程设计之网络聊天程序的设计与实现

计算机网络课程设计之网络聊天程序的设计与实现

2024-07-16 09:09| 来源: 网络整理| 查看: 265

前言

计算机网络课程设计开始,要求用C/C++,而且有些题目还要有图形界面,因此决定用Qt写图形界面,同时决定用一个程序完成所有的实验设计。

白嫖容易,创作不易,本文原创,转载请注明!!! 源码和可运行程序: 链接:https://pan.baidu.com/s/1A9KctmpP2JJgyW2wLrehIg 提取码:Lin2

计算机网络课程设计: 计算机网络课程设计之网络聊天程序的设计与实现 计算机网络课程设计之Tracert与Ping程序设计与实现 计算机网络课程设计之基于 IP 多播的网络会议程序 计算机网络课程设计之网络嗅探器的设计与实现 计算机网络课程设计之电子邮件客户端程序设计与实现 计算机网络课程设计之TELNET 终端设计与实现 计算机网络课程设计之网络代理服务器的设计与实现 计算机网络课程设计之简单 Web Server 程序的设计与实现

Qt入门系列: Qt学习之C++基础 Qt学习之Qt安装 Qt学习之Qt基础入门(上) Qt学习之Qt基础入门(中) Qt学习之Qt基础入门(下)

创作不易,整个课程设计程序3000多行代码,所有实验都写在了一个程序中,时间有限,能力不足,转载望注明!!! 本文链接 个人博客:https://ronglin.fun/archives/264 PDF链接:见博客网站 CSDN: https://blog.csdn.net/RongLin02/article/details/122509928

实验题目

网络聊天程序的设计与实现

实验目的

了解 Socket 通信的原理,在此基础上编写一个聊天程序。

总体设计

(含背景知识或基本原理与算法、或模块介绍、设计步骤等) 本次设计客户端用了Qt,Qt的一个很鲜明的特色就是可以使用槽函数异步处理数据。 服务器端用了Java,因为要用到多线程处理每一个客户端,同时用到了很多阻塞式方法,Java的库中对于多线程的处理十分方便,因此服务器用Java书写。

客户端

在Qt中创建一个TCP连接十分简单 参考博客:QT5实现简单的TCP通信 首先使用QT的网络套接字需要.pro文件中加入一句:

QT += network

客户端的代码比服务器稍简单,总的来说,使用QT中的QTcpSocket类与服务器进行通信只需要以下5步:

创建QTcpSocket套接字对象 QTcpSocket* socket = new QTcpSocket(); 使用这个对象连接服务器 socket->connectToHost(IP, port); 使用write函数向服务器发送数据 int result = socket->write(data); 当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data); void MainWindow::socket_Read_Data() { QByteArray buffer; //读取缓冲区数据 buffer = socket->readAll(); } 断开与服务器的连接 关于close()和disconnectFromHost()的区别,可以按F1看帮助 socket->disconnectFromHost(); //socket->close() 服务器

虽然服务器端用的是Java写的,但是还是提一下Qt中如何创建服务器

Qt TCP服务器

服务器除了使用到了QTcpSocket类,还需要用到QTcpSever类。即便如此,也只是比客户端复杂一点点,用到了6个步骤:

创建QTcpSever对象 QTcpSocket server = new QTcpServer(); 侦听一个端口,使得客户端可以使用这个端口访问服务器 这里的第一个参数是QHostAddress,在Qt的assistant(帮助文档)有详细的说明 server->listen(QHostAddress::Any, port); 当服务器被客户端访问时,会发出newConnection()信号,因此为该信号添加槽函数,并用一个QTcpSocket对象接受客户端访问 connect(server,&QTcpServer::newConnection,this,&MainWindow::server_New_Connect); void MainWindow::server_New_Connect() { //获取客户端连接 socket = server->nextPendingConnection(); } 使用socket的write函数向客户端发送数据 int result = socket->write(data); 当socket接收缓冲区有新数据到来时,会发出readRead()信号,因此为该信号添加槽函数以读取数据 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data); void MainWindow::socket_Read_Data() { QByteArray buffer; //读取缓冲区数据 buffer = socket->readAll(); } 取消侦听 server->close();

Qt异步处理数据用起来很方便,因为connect函数的存在,程序不用阻塞,可以等待槽函数的触发。

Java TCP服务器

接下来说明Java如何创建一个TCP服务器 参考博客:TCP通信的Java实现

先创建一个ServerSocket类调用accept()方法获取连接,此方法阻塞式方法获取客户端的输入流,来读客户端数据获取客户端的输出流,来向客户端写数据关闭所有对象 代码如下 import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class Server { public static void main(String[] args) { //1. 创建服务器ServerSocket对象 try { ServerSocket serverSocket = new ServerSocket(6666); //2. 获取客户端请求对象Socket Socket socket = serverSocket.accept(); //3. 获取字节输入流对象 InputStream inputStream = socket.getInputStream(); //4. 读取客户端数据 byte[] bytes = new byte[1024]; int len = inputStream.read(bytes); System.out.println(new String(bytes,0,len)); //5. 获取字节输出流对象 OutputStream outputStream = socket.getOutputStream(); //6. 向客户端回写数据 outputStream.write("I am OK.".getBytes()); //7. 释放资源 socket.close(); serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } 详细设计

(含主要的数据结构、程序流程图、关键代码等)

数据格式

首先是数据的数据格式,这里我设置了一个Message类,格式如下:

TYPE: Information FROM: 11809 TO: 11810 TIME: 2022-01-05 17:18:49 CONTENT: test测试

一共是5项数据:

TYPE,表示数据的类型,类型一共有3种,一个是Heartbeat,表示心跳,心跳类的数据包只有一个Type类型的数,其余都是0或者null,第二种是UserList,表示用户列表,当有客户端连入TCP服务器或者与其断开的时候,会广播发送一次UserList数据包,用来告诉所有客户端更新用户列表。最后一个是Information数据包,用来封装消息。FROM,在Information中表示数据的发送者TO,在Information中表示数据的接收者,TCP服务器通过此来把数据发送给相应的TCPClientTIME,时间,注意虽然发送者在发送的时候会填入一个时间到Information类数据包中,但是当数据到达服务器时,服务器会以本身的时间来更新这部分,以防客户端本身的时间错误CONTENT,表示内容,即正文部分。 服务器

如果要实现聊天室,首先要先设计一个服务器,服务器的设计主要是Java多线程实现 下面简单说明一下设计过程

一共有3类线程:

第一类线程是在Main中的一个while(true),主要是向服务器中所有连接的客户端发送心跳包,每500ms发送一个心跳包,如果发送失败则说明客户端已经断开,然后广播一个UserList类型的数据,来告诉客户端更新列表。第二类线程是TCPServer线程,该线程的主要作用就是用来处理阻塞的accept()方法,当连接成功一个客户端之后,将其添加到一个维护的ArrayList,然后再次while(true)阻塞accept()方法。第三类线程就是用来处理所有的客户端的数据,主要是处理阻塞的read()方法,用来监听客户端的输入。

同时每一个客户端的标识是用他们本身的本地Port数据来标识。

客户端

在这里插入图片描述 界面如上,当点击登录的时候,socket开始连接,ip地址为自行写死的"127.0.0.1"端口也是写死的"60001",然后登录之后收到来自服务器的UserList类型的数据包,然后更新自己的在线用户栏目,复位就是清0一个计数变量,清空按钮是清空上下的textEdit控件,启动新进程是为了调试,主要是用来启动一个新的子进程,发送按钮的逻辑是先清空发送栏,然后调用write()方法,把数据打包成Message格式,然后发送给服务器。 需要注意的是,要时刻注意判定是否在登录的状态下。

实验结果与分析

下面展示一下过程 在这里插入图片描述 可以看到连接成功,然后进行数据交换 在这里插入图片描述

可以看到数据发送成功,同时在服务器端也能获得数据 当第二个客户端断开: 在这里插入图片描述 当第二个断开的时候,可以在服务器端看到14760已经断开,同时第一个客户端可以看到14760已经断开了。

小结与心得体会

因为本实验用的是Qt和Java已经封装好的TCP库,所以用起来很方便,因为以前已经有TCP服务开发经验所以本实验开发比较简单。 个人觉得本次设计亮点在于设计Message类型和添加了心跳包。 =w=



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有