您的位置:首页 > 其它

多线程与聊天室程序的创建

2013-08-04 15:17 274 查看
1. 主线程和线程1在交替运行:

//因为我们要访问windows给我们提供的API函数,

//所以要包含一个windows.h文件

#include <windows.h>

#include <iostream.h>

//线程函数

DWORD WINAPI Fun1Proc(

LPVOID lpParameter

);

int index=0;

void main()

{

//当程序启动运行的时候,就会产生一个主线程,那么main()函数

//是作为主线程的入口函数。

HANDLEhThread1;

hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);

//关闭线程的句柄,但是并没有终止我们新创建的线程

//我们应该在不再使用线程的句柄时候将其关闭掉,让这个线程的内核对象

//的引用计数-1

CloseHandle(hThread1);

while(index++<1000)

cout<<"main thread isrunning"<<endl;

//去指定一个时间间隔,在这个时间间隔内,线程是暂停运行的

//当它暂停执行的时候,就是它主动放弃了执行的机会

// Sleep(10);

}

DWORD WINAPI Fun1Proc(

LPVOID lpParameter

)

{

while(index++<1000)

cout<<"thread1 isrunning"<<endl;

return0;

}

//主线程在时间片之内运行,当时间片到期之后,操作系统会选择

//线程1开始运行,同样为线程1分配一个时间片,线程1运行一段

//时间之后,它的时间到期了,那么操作系统会选择主线程开始运行

//于是我们就可以看到主线程和线程1在交替运行。

//这就是主线程和线程1在单CPU平台下的交替运行,如果在多CPU中它们

//就可以真正的并发运行了。

2. 编写一个程序模拟火车站的购票系统:

火车站的购票系统是采用多线程实现的:

//因为我们要访问windows给我们提供的API函数,

//所以要包含一个windows.h文件

#include<windows.h>

#include<iostream.h>

//线程函数

DWORD WINAPIFun1Proc(

LPVOID lpParameter

);

DWORDWINAPI Fun2Proc(

LPVOID lpParameter

);

intindex=0;

inttickets=100;

//对于主线程来说,在这两个线程买完这100张票前,主线程不能退出

//如果这个主线程退出了,那么这个进程也就退出了,那么线程1和

//线程2也就跟着退出。

voidmain()

{

//当程序启动运行的时候,就会产生一个主线程,那么main()函数

//是作为主线程的入口函数。

HANDLE hThread1;

HANDLE hThread2;

hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);

hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);

//关闭线程的句柄,但是并没有终止我们新创建的线程

//我们应该在不再使用线程的句柄时候将其关闭掉,让这个线程的内核对象

//的引用计数-1

CloseHandle(hThread1);

CloseHandle(hThread2);

//让主线程睡眠4秒钟,当执行sleep的时候,主线程就放弃了它执行的权利

//进入等待状态,这个时间的主线程它是不占用CUP的执行时间的。

Sleep(4000);

}

DWORDWINAPI Fun1Proc(

LPVOID lpParameter

)

{

while(TRUE)

{

//做一个循环让线程不断的运行,不断地销售火车票

if(tickets>0)

{

Sleep(1);

cout<<"thread1sell ticket: "<<tickets--<<endl;

}

//如果票卖完了,则终止循环

else

break;

}

return 0;

}

DWORDWINAPI Fun2Proc(

LPVOID lpParameter

)

{

while(TRUE)

{

//做一个循环让线程不断的运行,不断地销售火车票

if(tickets>0)

{

Sleep(1);

cout<<"thread2sell ticket: "<<tickets--<<endl;

}

//如果票卖完了,则终止循环

else

break;

}

return 0;

}

线程的同步,利用这个函数可以创建一个互斥对象,利用这个互斥对象完成线程的同步。

3. 采用多线程技术编写一个网络聊天室程序:

BOOL CChatDlg::OnInitDialog()

{

InitSocket();

//定义一个指针,并给它分配空间

RECVPARAM*pRecvParam = new RECVPARAM;

//对结构体这两个当中的成员进行初始化

pRecvParam->sock= m_socket;

//所有跟窗口有关的类,都有一个数据成员叫m_hWnd,

//它保存了跟这个窗口类相关的句柄

pRecvParam->hwnd= m_hWnd;

//创建一个线程

HANDLEhThread = CreateThread( NULL, 0, RecvProc, (LPVOID)pRecvParam, 0, NULL);

//关闭线程句柄

CloseHandle(hThread);

returnTRUE; // return TRUE unless you set the focus to a control

}

//在InitSocket这个函数中,对套接字进行初始化

BOOL CChatDlg::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);

//让它接收发送到本地任意IP地址数据

addrSock.sin_addr.S_un.S_addr= htonl(INADDR_ANY);

//定义一个整型变量,让它接收bind的返回值

intretval;

retval = bind(m_socket, (SOCKADDR*)&addrSock, sizeof(SOCKADDR));

if( SOCKET_ERROR == retval )

{

//关闭套接字

closesocket(m_socket);

MessageBox("绑定失败");

returnFALSE;

}

return TRUE;

}

//线程函数

DWORD WINAPI CChatDlg::RecvProc(LPVOIDlpParameter)

{

//首先取出我们传入的两个参数值

SOCKETsock = ((RECVPARAM*)lpParameter)->sock;

HWNDhWnd = ((RECVPARAM*)lpParameter)->hwnd;

//接收数据

//在接收数据之前,定义一个套接字地址结构的变量

//它主要是用来接收发送端的地址信息

SOCKADDR_IN addrFrom;

//主要是接收返回的地址结构体的长度,这个变量要初始化

intlen = sizeof(SOCKADDR);

//字符数组,用来接收到来的数据

charrecvBuf[200];

//用来存放格式化后的数据

chartempBuf[300];

//让接收线程可以不断的运行下去

intretval;

while(TRUE)

{

//retval用来接收recvfrom的返回值

retval= recvfrom(sock, recvBuf, 200, 0, (SOCKADDR*)&addrFrom, &len );

if(SOCKET_ERROR == retval )

break;

//如果没有错误,可以做一个格式化,将格式化中的数据放到tempBuf当中,

//取出发送端的IP地址,调用inet_ntoa将地址转化为点分十进制表示的字符串

sprintf(tempBuf, "%s说: %s",inet_ntoa(addrFrom.sin_addr), recvBuf );

//将数据传给对话框(可以采用发送消息的方式,将这个消息传给对话框)

::PostMessage(hWnd, WM_RECVDATA, 0, (LPARAM)tempBuf);

}

return0;

}

//3 消息响应函数的实现

void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)

{

//定义一个对象,取出数据

CStringstr = (char*)lParam;

//定义一个对象,用来接收旧的数据

CStringstrTemp;

//获取文本

GetDlgItemText(IDC_EDI_RECV, strTemp );

//增加一个换行

str+= "\r\n";

//加上先前的数据

str+= strTemp;

SetDlgItemText(IDC_EDI_RECV,str );

}

//发送端

void CChatDlg::OnBtnSend()

{

//用来接收IP地址

DWORDdwIP;

//首先得到这个控件的CWnd指针

((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);

//得到IP之后,可以定义一个地址结构体的变量

SOCKADDR_INaddTo;

addTo.sin_family= AF_INET;

addTo.sin_port= htons(6000);

addTo.sin_addr.S_un.S_addr= htonl(dwIP);

//得到要发送的数据

CStringstrSend;

GetDlgItemText(IDC_EDIT_SEND,strSend);

sendto(m_socket,strSend, strSend.GetLength()+1, 0,

(SOCKADDR*)&addTo,sizeof(SOCKADDR));

SetDlgItemText(IDC_EDIT_SEND,"");

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: