基于UDP的网络聊天程序

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

创建一个MFC的对话框工程Chat,界面如图

下面是实现步骤:

一、调用Afxstock全局函数初始化套接字库,在CChatApp::InitInstance()中添加代码:

if (!AfxSocketInit())

{

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

return FALSE;

}

二、在CChatDlg类中添加一个成员函数:stocketInit(),并在CChatDlg::OnInitDialog()中调用一下,代码如下:

BOOL CChatDlg::stocketInit()

{

m_socket=socket(AF_INET,SOCK_DGRAM,0);

if (INVALID_SOCKET==m_socket)

{

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

return FALSE;

}

SOCKADDR_IN socket_in;

socket_in.sin_family=AF_INET;

socket_in.sin_port=htons(3000);

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

int retval;

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

if (SOCKET_ERROR==retval)

{

closesocket(m_socket);

MessageBox("绑定套接字失败!");

return FALSE;

}

return TRUE;

}

三、在CChatDlg::OnInitDialog()中创建一个线程,用于接收数据。这是本程序的关键一步,

1、接收数据的recvfrom函数会一直等待数据的到来,如果放在主线程中会赌塞系统,所以必须在建一个线程实现。

2、线程必须接收对话框传来的套接字,用来接收数据,而得到的数据必须回传给对话框显示出来,但是线程只能接收一个LPVOID型的参数,要同时接受2个参数,就需要提前定义一个struct,里面包含2个成员:sock和hwnd,把这个结构的指针做为参数传递给线程。

3、数据的回传通过自定义消息实现,把接收到的数据作为消息的附件参数传给对话框。

创建线程的代码:

BOOL CChatDlg::OnInitDialog()

{ ............

RECVPARAM* pRecvparam=new RECVPARAM; //RECVPARAM是含2个参数的结构体

pRecvparam->socket=m_socket;

pRecvparam->hwnd=m_hWnd;

HANDLE

hThead=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvparam,0,NULL);

CloseHandle(hThead);

...............

}

线程代码:

DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)

{

SOCKET sock;

HWND hwnd;

sock=((RECVPARAM*)lpParameter)->socket; //先取出2个参数

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

delete lpParameter;

SOCKADDR_IN addrFrom;

int len=sizeof(SOCKADDR);

//AfxMessageBox("线程启动");

char recvBuf[200];

char tempBuf[300];

int revale;

while (TRUE)

{

revale=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len); //接收数据

if (SOCKET_ERROR==revale)

break;

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

::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf); //给对话框发消息,传递接收的数据

//AfxMessageBox(tempBuf);

}

return TRUE;

}

四、对话框中加一个对消息的响应函数。需要在3个地方加代码:函数原型说明、消息映射、函数代码。

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

{

CString strRecv=(char*)lParam;

CString strTemp;

GetDlgItemText(IDC_EDIT_RECV,strTemp);

strTemp+="\r\n";

strTemp+=strRecv;

SetDlgItemText(IDC_EDIT_RECV,strTemp);

}

五、接收部分完成,设计发送部分,给“发送”按钮增加一个响应函数

void CChatDlg::OnButtonSend()

{

// TODO: Add your control notification handler code here

DWORD dwIp;

((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS))->GetAddress(dwIp);

SOCKADDR_IN addrTo;

addrTo.sin_family=AF_INET;

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

addrTo.sin_port=htons(3000);

CString strSend;

GetDlgItemText(IDC_EDIT_SEND,strSend);

sendto(m_socket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCK ADDR));

SetDlgItemText(IDC_EDIT_SEND,"");

//char strS[200];

//strS=strSend.Left(strSend.GetLength());

}

总结体会和存在的问题:

函数参数的传递非常巧妙;自定义消息的响应可以当中断使用;对话框控件的使用非常灵活。

相关文档
最新文档