如果您无法下载资料,请参考说明:
1、部分资料下载需要金币,请确保您的账户上有足够的金币
2、已购买过的文档,再次下载不重复扣费
3、资料包下载后请先用软件解压,在使用对应软件打开
实验四多线程聊天室的创建预备知识:程序、进程和线程程序是计算机指令的集合,它以文件的形式存储在磁盘上。进程:通常被定义为一个正在运行的程序的实例,是一个程序在其自身的地址空间中的一次执行活动。进程是资源申请、调度和独立运行的单位,因此,它使用系统中的运行资源;而程序不能申请系统资源,不能被系统调度,也不能作为独立运行的单位,因此,它不占用系统的运行资源。进程由两个部分组成:1、操作系统用来管理进程的内核对象。内核对象也是系统用来存放关于进程的统计信息的地方。2、地址空间。它包含所有可执行模块或DLL模块的代码和数据。它还包含动态内存分配的空间。如线程堆栈和堆分配空间。进程是不活泼的。进程从来不执行任何东西,它只是线程的容器。若要使进程完成某项操作,它必须拥有一个在它的环境中运行的线程,此线程负责执行包含在进程的地址空间中的代码。单个进程可能包含若干个线程,这些线程都“同时”执行进程地址空间中的代码。每个进程至少拥有一个线程,来执行进程的地址空间中的代码。当创建一个进程时,操作系统会自动创建这个进程的第一个线程,称为主线程。此后,该线程可以创建其他的线程。线程运行:操作系统为每一个运行线程安排一定的CPU时间——时间片。系统通过一种循环的方式为线程提供时间片,线程在自己的时间内运行,因时间片相当短,因此,给用户的感觉,就好像线程是同时运行的一样。如果计算机拥有多个CPU,线程就能真正意义上同时运行了。实验步骤:新建一个基于对话框、支持Windowsockets的MFC可执行应用程序(exe);设计如图所示界面:对话框控件ID设置接收数据框架:IDC_STATIC接收数据编辑框:IDC_EDIT_RECV发送数据编辑框:IDC_STATICIP地址控件:IDC_IPADDRESS1发送数据编辑框:IDC_EDIT_SEND发送命令按钮:IDC_BTN_SEND在MFC中调用AfxSocketInit()加载套接字库,参考MSDN两个版本:在CWinApp::InitInstance中调用;在StdAfx.h中包含Afxsock.h头文件源码:if(!AfxSocketInit()){AfxMessageBox("加载套接字库失败!");returnFALSE;}创建并初始化套接字,为C***Dlg类添加一个private权限SOCKET类型的变量m_socket和一个BOOL类型的InitSocket()成员函数,在OnInitDialog()函数中调用InitSocket()函数实现初始化:函数实现代码如下:BOOLCCHATDlg::InitSocket(){m_socket=socket(AF_INET,SOCK_DGRAM,0);if(INVALID_SOCKET==m_socket){MessageBox("套接字创建失败!");returnFALSE;}SOCKADDR_INaddrSock;addrSock.sin_family=AF_INET;addrSock.sin_port=htons(6000);addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);intretval;retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));if(SOCKET_ERROR==retval){closesocket(m_socket);MessageBox("绑定失败!");returnFALSE;}returnTRUE;}实现接收端功能接收数据的时候会有阻塞,处理方式使用一个单独的线程,采用CreateThread();(1)先在C***Dlg类的前面定义一个结构体:structRECVPARAM{SOCKETsock;HWNDhwnd;};(2)在OnInitDialog()函数中定义一个RECVPARAM类型的指针,然后初始化:RECVPARAM*pRecvParam=newRECVPARAM;pRecvParam->sock=m_socket;pRecvParam->hwnd=m_hWnd;HANDLEhThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);CloseHandle(hThread);(3)在C***Dlg类添加函数成员,写线程函数:staticstaticDWORDWINAPIRe