? 在VS下建一個對話框的MFC程序UDPChat,去掉所有帶的控件。加入以下控件:
按鈕一個?? IDC_BTN_SEND
編程框三個 IDC_EDIT_PORT(端口號),IDC_EDIT_REC(顯示接收到的消息),IDC_EDIT_SEND(輸入發(fā)送內(nèi)容)
IP控件一個 IDC_IPADDRESS1
UDPChatDlg.h中加入
#define??? WM_RECDATA WM_USER+1
來定義一個消息號,用來處理接收到消息的事件
然后是以下方法聲明:
private:
????bool?InitSocket(void);
????static?DWORD?WINAPI?RecProc(LPVOID?lpParam);
????afx_msg?LRESULT?OnRecData(WPARAM?wParam,LPARAM?lParam);
????afx_msg?void?OnBnClickedBtnSend();
消息映射里加入兩條:
ON_MESSAGE(WM_RECDATA, OnRecData)//處理收到消息事件
ON_BN_CLICKED(IDC_BTN_SEND, &CTcpChatDlg::OnBnClickedBtnSend)//處理按鈕點擊事件
至此,萬事具備,只欠東風(fēng)。
首先窗口初始化函數(shù)OnInitDialog里加入
????//構(gòu)造一個新線程用于監(jiān)聽接收
????HANDLE?hThread?=?
????????CreateThread(NULL,?0,?RecProc,?(LPVOID)m_hWnd,?0,?NULL);
????CloseHandle(hThread);
????((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->SetAddress(127,?0,?0,?1);
????SetDlgItemText(IDC_EDIT_PORT,?_T("6000"));
后面就是四個相關(guān)的成員函數(shù),需要注意的是在線程必須使用靜態(tài)函數(shù)或者全局函數(shù),因為這程序一開始,線程就運行起來了,而成員方法在那個時候可能還沒有生成出來。
bool?CTcpChatDlg::InitSocket()
{
????WORD?wVersionRequested;
????WSADATA?wsaData;
????wVersionRequested?=?MAKEWORD(?2,?2?);
????int?err?=?WSAStartup(?wVersionRequested,?&wsaData?);
????if?(?err?!=?0?)?{
????????/*?Tell?the?user?that?we?could?not?find?a?usable?*/
????????/*?WinSock?DLL.??????????????????????????????????*/
????????return?false;
????}
????if?(?LOBYTE(?wsaData.wVersion?)?!=?2?||
????????HIBYTE(?wsaData.wVersion?)?!=?2?)?{
????????????/*?Tell?the?user?that?we?could?not?find?a?usable?*/
????????????/*?WinSock?DLL.??????????????????????????????????*/
????????????WSACleanup(?);
????????????return?false;?
????}
????return?true;
}
DWORD?WINAPI?CTcpChatDlg::RecProc(LPVOID?lpParam)
{
????HWND?hWnd?=?(HWND)lpParam;
????//-----------------------------------------------
????//?Create?a?receiver?socket?to?receive?datagrams
????SOCKET?RecvSocket?=?socket(AF_INET,?SOCK_DGRAM,?0);
????if(INVALID_SOCKET?==?RecvSocket)
????{????????????
????????::AfxMessageBox(_T("socket創(chuàng)建失敗"));
????????return?1;
????}
????//-----------------------------------------------
????//?Bind?the?socket?to?any?address?and?the?specified?port.
????SOCKADDR_IN?RecvAddr;
????RecvAddr.sin_family?=?AF_INET;
????RecvAddr.sin_port?=?htons(6000);
????RecvAddr.sin_addr.S_un.S_addr?=?htonl(INADDR_ANY);
????if(SOCKET_ERROR?==?bind(RecvSocket,?(SOCKADDR?*)?&RecvAddr,?sizeof(RecvAddr)))
????{
????????closesocket(RecvSocket);
????????::AfxMessageBox(_T("bind失敗"));
????????return?1;
????}
????//-----------------------------------------------
????//?Call?the?recvfrom?function?to?receive?datagrams
????//?on?the?bound?socket.
????int?retval;
????char?RecvBuf[1024];
????char?tmpBuf[1024];
????sockaddr_in?SenderAddr;
????int?SenderAddrSize?=?sizeof(SenderAddr);
????while(true)
????{
????????retval?=?recvfrom(RecvSocket,?
????????????RecvBuf,?
????????????1024,?
????????????0,?
????????????(SOCKADDR?*)&SenderAddr,?
????????????&SenderAddrSize);
????????if(SOCKET_ERROR?==?retval)
????????{
????????????CString?strError;
????????????strError.Format("error?code?:?%d",?WSAGetLastError());
????????????::AfxMessageBox(strError);
????????????break;
????????}
????????sprintf_s(tmpBuf,?1024,?"收到%s消息:?%s",?inet_ntoa(SenderAddr.sin_addr),?RecvBuf);
????????//發(fā)送消息
????????::PostMessage(hWnd,?WM_RECDATA,?0,?(LPARAM)tmpBuf);
????}
????//清理工作
????closesocket(RecvSocket);
????WSACleanup();
????return?0;//成功
}
LRESULT?CTcpChatDlg::OnRecData(WPARAM?wParam,LPARAM?lParam)
{
????CString?str((char*)lParam);
????CString?origin;
????GetDlgItemText(IDC_EDIT_REC,origin);
????str?+=?"\r\n";
????str?+=?origin;
????SetDlgItemText(IDC_EDIT_REC,str);
????SetDlgItemText(IDC_EDIT_SEND,?_T(""));
????return?0;
}
void?CTcpChatDlg::OnBnClickedBtnSend()
{
????DWORD?dwIP;
????((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);
????CString?strPort;
????GetDlgItemText(IDC_EDIT_PORT,?strPort);
????//創(chuàng)建發(fā)送地址信息
????SOCKADDR_IN?addrTo;
????addrTo.sin_family?=?AF_INET;
????addrTo.sin_port?=?htons(atoi(strPort));
????addrTo.sin_addr.S_un.S_addr?=?htonl(dwIP);
????CString?strMsg;
????GetDlgItemText(IDC_EDIT_SEND,?strMsg);
????SOCKET?sock?=?socket(AF_INET,?SOCK_DGRAM,?0);
????if(SOCKET_ERROR?==?
????????sendto(
????????sock,?strMsg,?
????????strMsg.GetLength()+1,?0,?
????????(SOCKADDR?*)&addrTo,?sizeof(addrTo)
????????))
????{
????????CString?strError;
????????strError.FormatMessage("Send?Failed,?Error?Code:?%d",?WSAGetLastError());
????????MessageBox(strError);
????}
????
????closesocket(sock);
}