分享

第十五课笔记(3)——多线程的网络聊天

 昵称6004610 2013-01-08

第十五课笔记(3)——多线程的网络聊天

(2012-03-21 19:28:11)

下面我们来编写多线程的网络聊天程序
环境新建一个基于对话框的应用程序

 

第一步:我们来设置资源库里面的内容

 

第二步:加载套接字库进行版本协商,进行加载套接字库

——这个代码我们可以在我们的APP中的InitInstance进行编写

 

if (!AfxSocketInit())

 

{

AfxMessageBox("加载套接字库失败!");

 

return FALSE;

}//这里我们通过条件语句来判断是否已经加载套接字库了

 

【注意】这里请我们千万不要忘了添加我们的头文件Afxsock.h

——我们在StdAfx.h中添加即可  #include <Afxsock.h>

 

第三步:我们来对我们的套接字库进行初始化

 

BOOL CChat1Dlg::InitSocket()

 

{

 

m_socket=socket(AF_INET,SOCK_DGRAM,0);//来创建一个套接字

 

if (INVALID_SOCKET==m_socket)//判断套接字是否已经创建成功

 

{

 

MessageBox("创建套接字失败!");

 

return FALSE;

 

}

 

SOCKADDR_IN addrsock;//定义一个地址结构体变量

 

addrsock.sin_family=AF_INET;

 

addrsock.sin_port=htons(6000);

 

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

 

 

int retval;

 

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

 

if (SOCKET_ERROR==retval)//判断是否绑定成功

 

{

 

closesocket(m_socket);

 

MessageBox("绑定失败!");

 

return FALSE;

 

}

 

 

return true;

 

 

}

【注意】只有上面的代码我们的套接字的初始化工作还没有完,我们还要在我们的Dlg类中的OnInitDialog()函数中调用一下这个初始化函数InitSocket(),这样才有效。

 

第四步:接下来我们来创建一个结构体,让他来记录相关信息(我们放在我们的CDlg中)

 

struct RECVPARAM 

 

{

 

SOCKET sock;

 

HWND hwnd;

 

};

 

第五步:我们利用我们刚刚创建的结构体来创建线程(在我们的OnInitDialog函数中)

 

RECVPARAM *pRecvParam=new RECVPARAM;

 

pRecvParam->sock=m_socket;

 

pRecvParam->hwnd=m_hWnd;

 

HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);

 

CloseHandle(hThread);

 

第六步:我们来创建一个线程函数

——(注意我们要将这个函数声明为全局函数或者如果你要将这个线程函数声明为Dlg的成员函数也可以,但是你必须将这个函数定义成静态的,因为静态的函数他不属于任何一个对象,他是属于这个类的)

线程函数的编写:

 

DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)

 

{

 

SOCKET sock=((RECVPARAM*)lpParameter)->sock;//取出我们传递的套接字

 

HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;//取出我们传递的套接字

 

delete lpParameter; //释放内存

 

SOCKADDR_IN addrFrom;//定义套接字的地址变量

 

int len=sizeof(SOCKADDR);

 

 

char recvBuf[200];

 

char tempBuf[300];

 

int retval;

 

while(TRUE)

 

{

 

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

 

if(SOCKET_ERROR==retval)//判断接受是否成功

 

break;

 

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

 

::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);//我们接下来将我们的数据传给我们的对话框,这里利用发送消息的方式来传递

 

}

 

return 0;

 

}

 

第七步:下面是消息响应函数的实现函数

 

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

 

{

 

CString str=(char*)lParam;

 

CString strTemp;

 

GetDlgItemText(IDC_EDIT_RECV,strTemp);//获取文本

 

str+="\r\n";//增加一个换行

 

str+=strTemp;

 

SetDlgItemText(IDC_EDIT_RECV,str);

 

}

 

第八步:我们来设置发送端

 

void CChatDlg::OnBtnSend() 

 

{

 

// TODO: Add your control notification handler code here

 

DWORD dwIP;

 

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

 

 

SOCKADDR_IN addrTo;

 

addrTo.sin_family=AF_INET;

 

addrTo.sin_port=htons(6000);

 

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

 

 

CString strSend;

 

GetDlgItemText(IDC_EDIT_SEND,strSend);//得到我们要发送的数据

 

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

 

(SOCKADDR*)&addrTo,sizeof(SOCKADDR));//发送数据

 

SetDlgItemText(IDC_EDIT_SEND,"");//将我们发送编辑框设置为空

 

}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多