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()定义为起一个成员函数,注意此处为静态函数,因为不是的话,会产生一个参数传递错误;

 



此聊天窗口程序没有调通;不知为什么窗口不显式输入内容

 

 

 

posted @ 2012-10-11 22:21  SolarJupiter  阅读(271)  评论(0编辑  收藏  举报