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

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,"");   

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值