vc++学习之15 多线程与聊天室程序的创建
区别:程序和进程、线程(轻量级进程)的概念;
利用window库函数建立一个主线程和子线程的一个轮流执行
#include <windows.h> #include <iostream.h> DWORD WINAPI func1proc(LPVOID lpParameter); int index=10; void main() { HANDLE hthread1; hthread1=CreateThread(NULL,0,func1proc,NULL,0,NULL);//创建一个线程 CloseHandle(hthread1);//关闭句柄,不关闭线程,减少引用计数,计数为0释放; cout<<"main thread is running\n"<<endl; Sleep(2000);//主进程睡眠,子进程才能执行,否则子进程不能获得执行; } DWORD WINAPI func1proc( LPVOID lpParameter // thread data ) { cout<<"Thread1 is running!\n"<<endl; return 0; }
本质是程序的执行就是主线程休眠之后,将控制权交给子进程的,子进程然后执行;
多线程注重访问共享变量时的互斥锁的问题
#include <windows.h> #include <iostream.h> DWORD WINAPI func1proc(LPVOID lpParameter); DWORD WINAPI func2proc(LPVOID lpParameter); int index=0; int tickets=100; HANDLE mutex; void main() { HANDLE hthread1; HANDLE hthread2; hthread1=CreateThread(NULL,0,func1proc,NULL,0,NULL);//创建一个线程 hthread2=CreateThread(NULL,0,func2proc,NULL,0,NULL); CloseHandle(hthread1);//关闭句柄,不关闭线程,减少引用计数,计数为0释放; //while(index++<100) //cout<<"main thread is running\n"<<endl; mutex=CreateMutex(NULL,false,NULL);//创建互斥锁 Sleep(2000);//主进程睡眠,子进程才能执行,否则子进程不能获得执行; } DWORD WINAPI func1proc( LPVOID lpParameter // thread data ) { while(true) { WaitForSingleObject(mutex,INFINITE);//得到mutex互斥对象,互斥对象线程ID设置为该线程ID, if (tickets>0) { Sleep(1); cout<<"thread1 sells tickets:"<<tickets--<<endl; } else break; ReleaseMutex(mutex);//释放互斥锁,因为他们访问了一个统一的全局变量ticket } return 0; }
//一旦一个线程正常结束时,就把互斥对象的内部ID设置为0; DWORD WINAPI func2proc( LPVOID lpParameter // thread data ) { while(true) { WaitForSingleObject(mutex,INFINITE); Sleep(1); if (tickets>0) { cout<<"thread2 sells tickets:"<<tickets--<<endl; } else break; ReleaseMutex(mutex); } return 0; }
c创建一个机遇对话框的聊天窗口;
首先设计好dialog窗口 包含2个组框,2个编辑窗口。一个按钮,一个IP编辑窗口;
2,然后在BOOL CChatApp::InitInstance()中添加标准socket的绑定函数,注意头问价加入socket。h
BOOL CChatApp::InitInstance() { if (!AfxSocketInit()) { AfxMessageBox("加载套接字失败!"); return FALSE; }
3在CChatDlg类里面添加成员变量和成员函数,并在OnInitDialog()调用次初始化函数;
BOOL CChatDlg::InitSocket() { m_socket=socket(AF_INET,SOCK_DGRAM,0); if (INVALID_SOCKET==m_socket) { MessageBox("套接字创建失败"); return FALSE; } SOCKADDR_IN addrsock; addrsock.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrsock.sin_family=AF_INET; addrsock.sin_port=6000; //bind到IP和端口上; int retval; retval=bind(m_socket,(sockaddr*)&addrsock,sizeof(sockaddr)); if (SOCKET_ERROR==retval) { closesocket(m_socket); MessageBox("套接子绑定失败"); return FALSE; } return TRUE; }
3创建线程的函数,因为createthread函数只能传入一个参数,所以利用传入结构体指针形式传入2个参数;
定义结构体:
struct RecvParm { SOCKET sock; HWND hwdn; };
初始化,并调用创建线程函数(CChatDlg::OnInitDialog())
RecvParm *pRecvParam=new RecvParm;//定义一个将要传入到Createthread里面的参数 pRecvParam->sock=m_socket;//初始化socket pRecvParam->hwdn=m_hWnd;//和窗口有关的都一个一个变量保存窗口的句柄 HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL); CloseHandle(hThread);//关闭句柄,减少计数;
实现线程处理函数RecvProc()定义为起一个成员函数,注意此处为静态函数,因为不是的话,会产生一个参数传递错误;
此聊天窗口程序没有调通;不知为什么窗口不显式输入内容
Edit By SolarJupiter