网络聊天室(MFC编程)

article/2025/11/6 16:49:58

本应用是一款简单的模拟qq聊天应用.主要分为服务器端与客户端

服务器select端:

客户端client:

服务器端代码如下:



select.cpp:

// select.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include "dataHandle.h"#include#pragma comment(lib, "ws2_32")

void SockInit();

int _tmain(int argc, _TCHAR* argv[])

{

SockInit();

SOCKET lisSock = socket(AF_INET, SOCK_STREAM, 0);

sockaddr_in addr;

addr.sin_family = AF_INET;

addr.sin_port = htons(8090);

addr.sin_addr.S_un.S_addr = ADDR_ANY;

bind(lisSock, (sockaddr*)&addr, sizeof(sockaddr));

listen(lisSock, 5);

fd_set fds;

FD_ZERO(&fds);

FD_SET(lisSock, &fds);  //将监听套接字加入数组中

timeval timeout;

timeout.tv_sec = 5;

timeout.tv_usec = 0;

while (1)

{

fd_set tmSet = fds;  //临时数组

//移除掉没有事件发生的套接字

// SELECT 在编程的过程中,经常会遇到许多阻塞的函数,

//好像read和网络编程时使用的recv, recvfrom函数都是阻塞的函数,

//当函数不能成功执行的时候,程序就会一直阻塞在这里,无法执行下面的代码。

//这是就需要用到非阻塞的编程方式,使用select函数就可以实现非阻塞编程。

select(0, &tmSet, 0, 0, &timeout);

SOCKET s[5];

int j = 0;

//剩下的都是有事件发生的套接字

for (int i = 0; i < tmSet.fd_count; i++)

{

if (tmSet.fd_array[i] == lisSock) //如果是监听监听套接字

{

SOCKET cliSock = accept(lisSock, 0, 0);

printf("新连接.\n");

FD_SET(cliSock, &fds);  //将已连接的套接字加入数组中

}

else

{

char recvBuf[1024] = { 0 };

int recvLen = recv(tmSet.fd_array[i], recvBuf, 1024, 0);

if (recvLen > 0)

{

//处理数据

HandleData(recvBuf,recvLen);

printf("%s\n",recvBuf);

}

else  //错误发生,或者客户端断开连接

{

printf("客户已断开\n");

FD_CLR(tmSet.fd_array[i], &fds);  //从数组中移除已端口的客户端

}

}

}

}

return 0;

}

void SockInit()

{

WORD wVersionRequested;

WSADATA wsaData;

int err;

wVersionRequested = MAKEWORD(2, 2);

err = WSAStartup(wVersionRequested, &wsaData);

if (err != 0) {

return;

}

if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)

{

WSACleanup();

return;

}

}


dataHandle.h 用于服务器接收到不同类型消息处理

#pragma once#include//处理收到的数据

bool HandleData(const char* recvData,int len);

dataHandle.cpp

#include "stdafx.h"

#include "dataHandle.h"

#include "netStruct.h"

//处理收到的数据

bool HandleData(const char* recvData,int len)

{

//printf("%s : %d", recvData, len);

short msgID = *(short*)recvData;

switch (msgID)

{

case TALKALL_MSGID:

{

//...给所有人的消息

const MSG_TALKALL* takAll = (MSG_TALKALL*)recvData;

printf("群聊消息: %s\n", takAll->Content);

}

break;

case TALKONE_MSGID:

{

//给某个人的消息

const MSG_TALKONE* takOne = (MSG_TALKONE*)recvData;

printf("私聊消息: %s : %s\n", takOne->userName, takOne->Content);

//takOne.useName

}

break;

case LOGIN_MSGID:

//登陆消息

break;

//.........

case FILEINFO_MSGID:

{

const MSG_SENDFILEINFO *fileInfo = (MSG_SENDFILEINFO*)recvData;

printf("文件路径:%s ,文件大小:%d\n", fileInfo->fileName, fileInfo->fileSize);

}

break;

case FILE_MSGID:

{

const MSG_SENDFILE *file = (MSG_SENDFILE*)recvData;

printf("文件内容:%s\n", file->fileBuf);

}

break;

default:

break;

}

return true;

}


netStruct.h 传输的信息结构体

#pragma once

#define TALKALL_MSGID 10001

#define TALKONE_MSGID 10002

#define LOGIN_MSGID 10003

#define SENDPIC_MSGID 10004

#define FILEINFO_MSGID 10005

#define FILE_MSGID 10006

//给所有人发的消息

struct MSG_TALKALL

{

short msgID;

char Content[1024];

};

//给某人发的消息

struct MSG_TALKONE

{

short msgID;

char userName[32];

char Content[1024];

};

struct MSG_SENDFILEINFO {

short msgID;

char fileName[256];

int fileSize;

};

struct MSG_SENDFILE {

short msgID;

int bufID;

short bufSize;

char fileBuf[1024];

};


客户端中

client.cpp

BOOL CclientApp::InitInstance(){

// 如果一个运行在 Windows XP 上的应用程序清单指定要

// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,

//则需要 InitCommonControlsEx()。  否则,将无法创建窗口。

INITCOMMONCONTROLSEX InitCtrls;

InitCtrls.dwSize = sizeof(InitCtrls);

// 将它设置为包括所有要在应用程序中使用的

// 公共控件类。

InitCtrls.dwICC = ICC_WIN95_CLASSES;

InitCommonControlsEx(&InitCtrls);

CWinApp::InitInstance();

AfxEnableControlContainer();

// 创建 shell 管理器,以防对话框包含

// 任何 shell 树视图控件或 shell 列表视图控件。

CShellManager *pShellManager = new CShellManager;

// 激活“Windows Native”视觉管理器,以便在 MFC 控件中启用主题

CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));

// 标准初始化

// 如果未使用这些功能并希望减小

// 最终可执行文件的大小,则应移除下列

// 不需要的特定初始化例程

// 更改用于存储设置的注册表项

// TODO: 应适当修改该字符串,

// 例如修改为公司或组织名

SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

AfxSocketInit();//网络初始化

clientSock sock;

sock.Create();

bool conRet = sock.Connect(_T("127.0.0.1"), 8090);

if (conRet == false) {

int errCode = GetLastError();

CString err;

err.Format(_T("连接服务器失败 : %d,请重试!"), errCode);

MessageBox(0, err, _T("错误"), MB_OK);

return FALSE;

}

Login log;//登录界面

INT_PTR res = log.DoModal();

if (res == IDOK) {

CclientDlg dlg(sock,log.userName);//发送信息界面,将socket传入对话框界面,以发信信息

m_pMainWnd = &dlg;

INT_PTR nResponse = dlg.DoModal();

if (nResponse == IDOK)

{

// TODO: 在此放置处理何时用

//  “确定”来关闭对话框的代码

}

else if (nResponse == IDCANCEL)

{

// TODO: 在此放置处理何时用

//  “取消”来关闭对话框的代码

}

else if (nResponse == -1)

{

TRACE(traceAppMsg, 0, "警告: 对话框创建失败,应用程序将意外终止。\n");

TRACE(traceAppMsg, 0, "警告: 如果您在对话框上使用 MFC 控件,则无法 #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS。\n");

}

// 删除上面创建的 shell 管理器。

if (pShellManager != NULL)

{

delete pShellManager;

}

#ifndef _AFXDLL

ControlBarCleanUp();

#endif

// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,

//  而不是启动应用程序的消息泵。

}


客户端登录界面:


在文字框输入文字,并发送出去代码如下:

void CclientDlg::OnBnClickedOk()

{

// TODO: 在此添加控件通知处理程序代码

//CDialogEx::OnOK();

UpdateData();

if (content_send.IsEmpty()) {

MessageBox(_T("请填入消息!"), _T("提示"), MB_OK);

return;

}

if (isSendFile == FALSE) {

/*

char *buff;

buff = (char *)content_send.GetBuffer(0);

m_sock.Send(buff, strlen(buff),0);//用多字节来发送

content_send = _T("");//清空内容

*/

/*

MSG_TALKONE takone;

takone.msgID = TALKONE_MSGID;

strcpy_s(takone.userName, userName);

strcpy_s(takone.Content, content_send.GetBuffer(0));

m_sock.Send(&takone, sizeof(MSG_TALKONE));

*/

MSG_TALKALL takall;

takall.msgID = TALKALL_MSGID;

strcpy_s(takall.Content, content_send.GetBuffer(0));

m_sock.Send(&takall, sizeof(MSG_TALKALL));

content_send = _T("");//清空内容

UpdateData(0);

}

else//发送文件

{

CreateThread(0, 0,sendFileThread, this,0,0);//方法只能为全局方法,不能为类方法

}

}

发送文件代码如下:

    DWORD WINAPI sendFileThread(LPVOID lpParameter)//开启多线程来传输文件

{

CclientDlg *dlg = (CclientDlg *)lpParameter;

CFileStatus fileStatus;

ULONGLONG size;

if (CFile::GetStatus(dlg->content_send.GetBuffer(0), fileStatus)) {

size = fileStatus.m_size;

}

MSG_SENDFILEINFO msgInfo;

msgInfo.msgID = FILEINFO_MSGID;

strcpy_s(msgInfo.fileName,dlg->content_send.GetBuffer(0));

msgInfo.fileSize = size;

dlg->m_sock.Send(&msgInfo, sizeof(MSG_SENDFILEINFO));

// 只读方式打开文件 

CFile file;

BOOL b = file.Open("C:\\Users\\WJ\\Desktop\\wifi.txt", CFile::modeRead);

while (b)

{

// 读取文件数据 

char ReadBuf[1016] = { 0 };

int ret = file.Read(ReadBuf, 100);

printf("%s\n", ReadBuf);

MessageBox(0, ReadBuf, 0, 0);

MSG_SENDFILE msg;

msgInfo.msgID = FILE_MSGID;

strcpy_s(msg.fileBuf, ReadBuf);

dlg->m_sock.Send(&msg, sizeof(MSG_SENDFILE));

if (ret < 100)// 如果到达文件结尾则中止循环

break;

}

// 关闭文件 

file.Close();

dlg->isSendFile = FALSE;

return TRUE;

}

运行结果如下:



http://chatgpt.dhexx.cn/article/XPjrtXXY.shtml

相关文章

《MFC编程》:钩子函数

《MFC编程》&#xff1a;钩子函数 《MFC编程》&#xff1a;钩子函数钩子函数简介作用类型 MFC窗口如何创建代码书写 《MFC编程》&#xff1a;钩子函数 钩子函数简介 钩子函数是Windows消息处理机制的一部分&#xff0c;通过设置“钩子”&#xff0c;应用程序可以在系统级对所…

《MFC编程》:MFC程序执行流程

《MFC编程》&#xff1a;MFC程序执行流程 《MFC编程》&#xff1a;MFC程序执行流程入口函数执行流程CWinApp的成员视频链接 《MFC编程》&#xff1a;MFC程序执行流程 入口函数 MFC程序的入口函数与win32程序一样&#xff0c;都是从WinMain入口。 但是MFC库已经实现了WinMain…

MFC基础入门

1 MFC入门 1.1 为什么学习MFC 在Windows平台上做GUI开发&#xff0c;MFC是一个不错的选择。 学习MFC不仅可以学习到MFC本身&#xff0c;而且可以学习MFC框架的设计思想。 1.2 Windows消息机制 基本概念解释 SDK&#xff1a;软件开发工具包(Software Development Kit)&…

MFC编程入门精讲

MFC&#xff08;Microsoft Foundation Classes,Microsoft基本类&#xff09;是一组预定义的类&#xff0c;封装了Windows API&#xff0c;对Windows编程来说是一种面向对象的方法。 所有使用MFC类的名称都已C开始&#xff0c;如CView。 1、简单的MFC程序 1.1 添加包括afxwin…

第三课——MFC编程

一、MFC概述 1. MFC简述 MFC不仅仅是一套基础类库&#xff0c;更是一种编程方式。 2. MFC由来 1987年微软公司推出了第一代Windows产品&#xff0c;并为应用程序设计者提供了Win16&#xff08;16位Windows操作系统&#xff09;API&#xff0c;在此基础上推出了Windows GUI&…

MFC编程入门

一、 什么是MFC&#xff1f; 如果你要建立一个Windows应用程序&#xff0c;应该如何下手&#xff1f; 好的开端是从设计用户界面开始。 首先&#xff0c;你要决定什么样的用户能使用该程序并根据需要来设置相应的用户界面对象。Windows用户界面有一些标准的控件&#xff0c;如按…

MFC最详细入门教程[转载]

本人在学习MFC的过程中&#xff0c;发现下面这个比较好的教程&#xff0c;这边转载记录一下 原文地址&#xff1a;MFC 最详细入门教程 From&#xff1a;https://blog.csdn.net/wang18323834864/article/details/78621633/ Visual Studio 2019&#xff1a;https://visualstudio.…

XAMPP详细安装教程

XAMPP安装教程 打开XAMPP安装包 等待安装完成 打开安装好的XAMPP 出现这种问题之后&#xff0c;我直接采用修改Apache端口号的方法 修改完Apache之后点击start运行MySQL&#xff0c;结果一直没开启成功&#xff0c;一直显示框框中的语句。百度几篇文章的结果就是找到regedit.e…

xampp使用教程方法免费分享

XAMPP是一个把Apache网页服务器与PHP、Perl及MySQL集合在一起的安装包&#xff0c;允许用户可以在自己的电脑上轻易的建立网页服务器。使用XAMPP您可以轻松的在本机调试您的PHP程序、CMS以及wordpress博客程序。本文主要分享一下XAMPP的使用教程。 XAMPP使用方法 1.下载XAMPP …

怎样在xampp中使用mysql以及配置xampp

怎样在xampp中使用mysql 以及配置xampp &#xff08;这里是在xampp中安装mysql的&#xff09; 第一步&#xff1a;安装xampp 找到xampp的安装包&#xff0c;双击下载&#xff1a; 我是安装在C盘的 安装好后&#xff0c;就会有下面页面 点 第二步&#xff1a;配置xampp&…

XAMPP汉化教程指南

xampp是一款新手学习PHP必备的软件&#xff0c;但是这款软件对于国人来说不太友好&#xff0c;因为他的控制面板界面只有英文和德文。 怎么汉化xampp xampp虽然好用&#xff0c;功能也比较简单&#xff0c;按钮功能好记&#xff0c;但是整个控制面板都是英文或者德文&#xf…

PHP 开发-XAMPP 安装

开发环境&#xff1a;Windows10&#xff0c;XAMPP&#xff08;x64-7.4.33&#xff09;&#xff0c;Netbeans。 XAMPP 安装 官网下载XAMPP安装包&#xff0c;我下载的版本 x64-7.4.33。安装包中相关软件版本&#xff08;官网上可查询&#xff09;&#xff1a; Apache 2.4.54M…

XAMPP安装和使用教程

最近由于某些情况&#xff0c;转入对PHP进行探讨&#xff0c;比较晚啦&#xff0c;呵呵&#xff01; 由于php在windows下配置虽不是很烦&#xff0c;但也难免出现误差&#xff0c;觉得集成工具也不错。下面把XAMPP的安装和使用教程转帖过来&#xff0c;以备我以后查阅。 XAMPP…

在xampp 中使用mysql的方法

法一、打开xampp 控制面板&#xff0c;启动mysql&#xff0c;然后打开shell,输入 mysql 即可 这里说一下最近碰到的问题&#xff1a;当我输入 mysql 的时候出错&#xff1a; Error Code: 1044. Access denied for user localhost to database mydb 原因&#xff1a;存在一个用…

xampp安装

XAMPP&#xff08;ApacheMySQLPHPPERL&#xff09;是一个功能强大的建站集成软件包&#xff0c; 是一个易于安装且包含 MySQL、PHP 和 Perl 的 Apache 发行版。小编在安装MySQL的路上不断碰壁&#xff0c;虽然是越挫越勇&#xff0c;但是&#xff0c;一旦挫太多次了也就没有那份…

XAMPP 使用教程

XAMPP 使用教程 文章目录 XAMPP 使用教程1.启动XAMPP。2.在Apache上点击start。3.访问http://localhonst&#xff0c;出现页面。 1.启动XAMPP。 2.在Apache上点击start。 3.访问http://localhonst&#xff0c;出现页面。 这说明你已经成功开启了本地服务器。&#xff08;在使用…

mac安装xampp及使用攻略

前言&#xff1a;最近接了一个商城的项目&#xff0c;后端要用到thinkphp6&#xff0c;听老板说很简单的框架&#xff0c;果断上手&#xff0c;不过在配置环境上&#xff0c;mac和windows差距很大&#xff0c;有很多坑&#xff0c;不过我已经一路踩过来了&#xff0c;建议喜欢的…

最详细的XAMPP的安装及使用教程(图文)

XAMPP的安装及使用教程 1、简介 XAMPP&#xff08;ApacheMySQLPHPPERL&#xff09;是一个功能强大的建站集成软件包。这个软件包原来的名字是 LAMPP&#xff0c;但是为了避免误解&#xff0c;最新的几个版本就改名为 XAMPP 了。它可以在Windows、Linux、Solaris、Mac OS X 等多…

XAMPP和MYSQL使用

1.下载 XAMPP 首先下载 XAMPP &#xff0c;您可以在本页面下方提供的链接直接点入官方网站下载。 2.安装 XAMPP 园子使用的是 XAMPP 的 Windows 版的安装包&#xff0c;下载后直接安装即可&#xff0c;安装过程所有选项保持默认即可。建议不要直接装在 C 盘。安装过程结束后&…

Xampp介绍、安装过程及使用方法

XAMPP&#xff08;ApacheMySQLPHPPERL&#xff09;是一个功能强大的建站集成软件包。 阅读一些资料&#xff0c;先整理如下&#xff1a; 软件介绍&#xff1a;http://baike.baidu.com/link?urlAGB3fqEAfvAKDp9ZpI-buHSS5A9bldAWbQbFP9C8_suyZgd5lSt68WgnUT4F6tn4nf5YhL144MMIp…