一、实验题目

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

二、实验目的 

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

总体设计

1. 基本原理

socket通信原理是一种“打开——读/写——关闭”模式的实现,服务器和客户端各自维护一个“文件”,在建立连接打开后,可以向文件写入内容供对方读取或者读取对方的内容,通讯结束时关闭文件。

Socket在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口,供应用层调用实现进程在网络中的通信。

Socket保证了不同计算机之间的通信,对于网站,通信模型是服务器与客户端之间的通信。两端都建立一个socket对象,然后通过socket对象对数据进行传输。通常服务器处于一个无限循环,等待客户端的连接。

2. 设计步骤

(1)服务器端编程的步骤

①加载套接字库,创建套接字WSAStartup();

在使用socket之前要进行版本的设定和初始化,应用程序只能在一次成功的WSAStartup()调用之后才能调用进一步的Windows Sockets API函数。根据版本初始化windows socket,返回0表示成功。

②创建套接字,使用TCP协议;

有套接字的接口才能进行通信。

③绑定套接字到一个 IP 地址和一个端口上(bind());

用bind()函数确定socket各种属性。

④将套接字设置为监听模式等待连接请求(listen());

⑤循环等待请求到来,每接受一个连接请求,返回一个新的对应于此次连接的套接字(accept());

accept()是一个阻塞函数,如果没有客户端请求,连接会一直等待在这里。该函数会返回一个新的套接字,这个新的套接字是用来与客户端通信的套接字,之前那个套接字是用来监听的套接字。

⑥用返回的套接字和客户端进行通信(send()/recv());

⑦关闭套接字,关闭加载的套接字库(closesocket())。

(2)客户端编程的步骤

①加载套接字库,创建套接字WSAStartup();

要连接的服务器的ip,因为现在服务器端就是本机,所以写本机ip,127.0.0.1一个特殊的IP地址,表示是本机的IP地址。

②向服务器发出连接请求(connect());

如果没有成功连接到服务器,一直循环,直至连接上为止。

③和服务器端进行通信(send()/recv());

④关闭套接字,关闭加载的套接字库(closesocket())。

详细设计 

程序流程图

实现代码

客户端

myClient.h

#ifndef MYCLIENT_H
#define MYCLIENT_H#include <QWidget>
#include <iostream>
#include "winsock2.h"
#include "stdlib.h"
#include "stdio.h"
#include "string"
#include <QThread>
#pragma comment (lib, "ws2_32.lib")QT_BEGIN_NAMESPACE
namespace Ui { class MyClient; }
QT_END_NAMESPACEclass MyClient : public QWidget
{Q_OBJECT
public:MyClient(QWidget *parent = nullptr);~MyClient();
private slots:void on_btcon_clicked();void on_btsend_clicked();void on_btclose_clicked();
private:Ui::MyClient *ui;
};class WorkThread : public QThread
{
public:WorkThread();
protected:void run();
};
#endif // MYCLIENT_H

main.cpp

主要是解决中文乱码问题,这里给出解决方案的一种

//添加库
#include <QTextCodec>
//设置编码GBK
QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));

myClient.cpp

#include "myclient.h"
#include "ui_myclient.h"
Ui::MyClient* mui;SOCKET serverSocket;//服务器MyClient::MyClient(QWidget *parent): QWidget(parent), ui(new Ui::MyClient)
{ui->setupUi(this);mui = ui;
}void MyClient::on_btcon_clicked()
{WorkThread* thread = new WorkThread();thread->start();
}void MyClient::on_btsend_clicked()
{char* buff;QString str = mui->tesend->toPlainText();QByteArray ba = str.toLocal8Bit();buff = ba.data();int r = send(serverSocket, buff, strlen(buff), NULL);//根据r的值查看是否发送成功
}void recvAndShow()
{int r, i = 0;char buff[256];while (1){memset(buff, 0, 256);r = recv(serverSocket, buff, 255, NULL);if (r > 0){mui->tbrecv->append(QString::fromLocal8Bit(buff,256));i++;}}
}void MyClient::on_btclose_clicked()
{closesocket(serverSocket);WSACleanup();return;
}MyClient::~MyClient()
{delete ui;
}WorkThread::WorkThread()
{
}void WorkThread::run()
{WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData) != 0;//成功==0if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)//请求版本失败{return ;}//创建socketserverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (serverSocket == INVALID_SOCKET)//创建socket失败!{return ;}//地址族SOCKADDR_IN addr = { 0 };//初始化地址int port = mui->leport->text().toInt();addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");addr.sin_family = AF_INET;addr.sin_port = htons(port);//端口号~65535尽量大于1Wint r = ::connect(serverSocket, (SOCKADDR*)&addr, sizeof addr);struct sockaddr_in conn;memset(&conn, 0, sizeof(struct sockaddr_in));int len = sizeof(conn);int ret = ::getsockname(serverSocket, (SOCKADDR*)&conn, &len);mui->luser->setText(QString(QLatin1String(inet_ntoa(conn.sin_addr)))+QString::number(ntohs(conn.sin_port)));if (r == -1)//连接服务器失败!{return ;}CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)recvAndShow, NULL, NULL, NULL);
}

Ui设计

服务端

myServer.h

#ifndef MYSERVER_H
#define MYSERVER_H#include <QWidget>
#include <iostream>
#include "winsock2.h"
#include "stdlib.h"
#include "stdio.h"
#include "string"
#include <QByteArray>
#include <QThread>
#pragma comment (lib, "ws2_32.lib")QT_BEGIN_NAMESPACE
namespace Ui { class MyServer; }
QT_END_NAMESPACEclass MyServer : public QWidget
{Q_OBJECT
public:MyServer(QWidget *parent = nullptr);~MyServer();
private slots:void on_btopen_clicked();void on_btclose_clicked();
private:Ui::MyServer *ui;
};class WorkThread : public QThread
{
public:WorkThread();
protected:void run();
};
void communication(LPVOID n);
#endif // MYSERVER_H

main.cpp

与客户端相同

myServer.cpp

#include "myserver.h"
#include "ui_myserver.h"
Ui::MyServer* mui;
SOCKET clientSocket[1024];
SOCKET serverSocket;
SOCKADDR_IN addr = { 0 };
int k = 0;MyServer::MyServer(QWidget *parent): QWidget(parent), ui(new Ui::MyServer)
{ui->setupUi(this);mui = ui;
}
MyServer::~MyServer()
{delete ui;
}
void MyServer::on_btopen_clicked()
{WorkThread* thread = new WorkThread();thread->start();
}
void MyServer::on_btclose_clicked()
{closesocket(serverSocket);closesocket(*clientSocket);WSACleanup();
}void communication(LPVOID n)
{char buff[256];int r;int i = (int)n;while (1){struct sockaddr_in sa;int len = sizeof(sa);if (!getpeername(clientSocket[i - 1], (struct sockaddr*)&sa, &len)){//printf("对方IP:%s ", inet_ntoa(sa.sin_addr));//printf("对方PORT:%d ", ntohs(sa.sin_port));}memset(buff, 0, sizeof(buff));r = recv(clientSocket[i - 1], buff, 255, NULL);if (r > 0){char* tem = buff;QString s = QString(QLatin1String(inet_ntoa(sa.sin_addr))) + ":" + QString::number(ntohs(sa.sin_port)) + ":" + QString::fromLocal8Bit(buff, 256);mui->tbinfor->append(s);for (int j = 0; j < k; j++){QByteArray ba = s.toLocal8Bit();char* buff1 = ba.data();int len = send(clientSocket[j], buff1, strlen(buff1), NULL);if (len <= 0) {return ;}}}}
}WorkThread::WorkThread()
{
}void WorkThread::run()
{WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData) != 0;//成功==0if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){return;}//创建socket//sockSer = socket(AF_INET, SOCK_STREAM,IPPROTO_TCP);//AF=Address family ,ipv4,TCP,0serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (serverSocket == INVALID_SOCKET){return;}//初始化地址int port = mui->leport->text().toInt();addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");addr.sin_family = AF_INET;addr.sin_port = htons(port);//端口号~65535int r = bind(serverSocket, (SOCKADDR*)&addr, sizeof(addr));if (r == -1)//绑定失败{return;}r = listen(serverSocket, 10);if (r == -1)//监听失败{return;}//连接//地址族SOCKADDR_IN cAddr = { 0 };int len = sizeof(cAddr);int i = 0;while (i < 1024){clientSocket[i++] = accept(serverSocket, (sockaddr*)&cAddr, &len);k++;if (clientSocket[i - 1] == SOCKET_ERROR)//错误的客户端!{closesocket(serverSocket);WSACleanup();return;}mui->tbuser->append(QString(QLatin1String(inet_ntoa(cAddr.sin_addr))) + ":" + QString::number(ntohs(cAddr.sin_port)) + QString::fromLocal8Bit(" 上线了!"));CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)communication, (LPVOID)i, NULL, NULL);}return;
}

ui设计

实验结果

基于C++的Qt网络编程——聊天客户端相关推荐

  1. 基于C++的Qt网络编程——基于 IP 多播的网络会议程序

    目录 一.实验题目 二.实验目的 三.总体设计 1.实验原理 2.设计步骤 四.详细设计 1.程序流程图 2.实验代码(部分) 五.实验结果与分析 六.小结与心得体会 一.实验题目 基于 IP 多播的 ...

  2. 基于Udp的Socket网络编程聊天程序

    1.新建一个工程区Net 在工作区中添加两个工程 NetSrv 和 NetClient 为两个工程添加库文件 (Link中) ws2_32.lib 2.在工程NetSrv中添加Server.cpp文件 ...

  3. QT网络编程开发服务端

    下一篇: QT网络编程开发客户端 文章目录 基于Qt的网络编程服务端 QTcpServer 配置 listen() close() newConnection() SINGL readyRead() ...

  4. qt android 网络编程实例,QT网络编程Tcp下C/S架构的即时通信实例

    先写一个客户端,实现简单的,能加入聊天,以及加入服务器的界面. #ifndef TCPCLIENT_H #define TCPCLIENT_H #include #include #include # ...

  5. Netty网络编程聊天项目

                                     Netty网络编程聊天项目 后端编写 导入依赖    <dependencies><dependency>&l ...

  6. 第十四章:Qt网络编程

    回顾: 第一章:Qt的概述 第二章:在Ubuntu编写第一个Qt程序 第三章:Qt的字符串和字符编码 第四章:Qt的信号和槽 第五章:Qt容器窗口(父窗口) 第六章:面向对象的Qt编程 第七章:Qt设 ...

  7. step5 . day2 网络编程 基于TPC协议的网络编程流程及API

    基于TCP协议的网络编程流程 服务器端: 1) socket(),创建套接字文件,用于连接 2) bind(), 绑定,把socket()函数返回的文件描述符和IP.端口号进行绑定; 3) liste ...

  8. Qt网络编程——TCP

    Qt网络编程--TCP 1. 概念 2. 服务器 3. 客户端 4. TCP服务器和客户端互传文件 5. 资源下载 1. 概念 TCP(Transmission Control Protocol, 传 ...

  9. 基于Linux的socket网络编程项目——游侠手机商城

    基于Linux的socket网络编程项目--游侠手机商城 一.项目说明 二.项目使用的技术 三.客户端搭建 四.服务器端搭建 一.项目说明 本项目是一个仿真手机商城类系统,基本功能: 登录界面功能:用 ...

  10. Qt网络编程实战之HTTP服务器-安晓辉-专题视频课程

    Qt网络编程实战之HTTP服务器-30196人已学习 课程介绍         设计了一个实用的HTTP服务器,基于Qt的网络框架实现.先详细介绍Qt的网络.IO.线程..自定义事件.配置文件等类库的 ...

最新文章

  1. 【Java】 LeetCode 622. 设计循环队列 (有关实现循环队列的讲解)
  2. 每个程序员都应该知道的10件事!
  3. LeetCode 763. 划分字母区间
  4. 编程疑难杂症の怪诞的【黄色警告】
  5. Github标星66.6k+:常见数据结构与算法的Python实现
  6. 摄像头poe供电原理_弱电知识之六:跟我学做监控,认识POE交换机与POE监控摄像头...
  7. uniapp 刷新后数据都没有了_环境温度传感器都没有连接,竟然还会有数据?
  8. MySQL遭遇DELETE误操作的回滚
  9. java guava 使用_使用Guava操作基本类型
  10. 欧洲杯推动夜间消费发展 便利蜂晚20时-凌晨2时服务人次创新高
  11. 接口测试之发包工具介绍
  12. SWAT模型在水文水资源、面源污染模拟中的实践技术应用
  13. 高级语言程序设计(C语言)----第一章 概述
  14. 美团外卖饿了么百度外卖竞品分析报告
  15. ligerui之控件列表初始化设置
  16. HTTPClient网络异常:java.lang.IllegalStateException: Content has been consumed
  17. Keras_examples
  18. vue.js——ElementUI表单向后台提交FormData数据
  19. Android 11.0 12.0在系统app安装第三方app弹出 解析安装包出现问题 的解决方案
  20. JSD-2204-Vue-ElementUI-Day06

热门文章

  1. 力软部署oracle,力软敏捷开发框架
  2. 力软下拉框多选_力软敏捷开发框架操作手册V7.06
  3. Drool实战系列(二)之eclipse安装drools插件
  4. 为什么有的PLC需要上电停止功能,能防止PLC变砖,可编程控制器 上电停止 串口通信 梯形图
  5. 【转】Myeclipse2017破解:成功解决me Trial expired 0 days ago mgeclipse It's now time to buy the best IDE for y
  6. Synergy两台电脑使用同一个鼠标和键盘
  7. matlab画图命令
  8. 为什么计算机连接u盘不显示内存不足,U盘明明有空间却提醒空间不足怎么解决...
  9. 2021泰迪杯数据分析技能赛B题解题思路分享
  10. java weblogic 下载,weblogic 下载 weblogic 12.2.1 for windows 64位的下载地址