创建一个基于对话框的MFC程序MultiThread,首先设置界面,并设置控件ID
接收数据是组合框,下面编辑框
发送数据是组合框,下面有IP地址框,编辑框,发送按钮,ID号如下
#define IDC_EDIT_RECV 1000 #define IDC_IPADDRESS1 1001 #define IDC_EDIT_SEND 1002 #define IDC_BTN_SEND 10031、首先加载套接字库,在InitStance()中调用AfxSocketInit(),在stdafx.h中加入“Afxsock.h”,AfxsocketInit()的调用一定在创建窗口之前,否者出现加载套接字失败的情况。
if (!AfxSocketInit())
{
AfxMessageBox(_T("加载套接字失败"));
return false;
}
2、在MFCmultithread.h中创建一个结构体,包含套接字和窗口的句柄,主要是投送消息时可以将两个消息同时传送。
struct RECVPARAM{
SOCKET socket;
HWND hWnd;
};
3、在MFCmultithread类中增加成员变量m_socket和成员方法InitSocket(),InitSocket()完成m_socket的初始化和绑定。
bool CMFCmultithreadDlg::InitSocket()
{
m_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (INVALID_SOCKET == m_socket)
{
AfxMessageBox(_T("套接字创建失败"));
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);
AfxMessageBox(_T("绑定失败!"));
return false;
}
return true;
}
4、创建一个线程函数,要么是全局的,要么是静态的,或者是类的成员方法,在这里创建为类的静态方法,它不属于具体的某一个类成员,属于类。
在MFCmultithread.h中添加静态的成员方法
static DWORD WINAPI RecvProc(LPVOID lpParameter);
DWORD WINAPI CMFCmultithreadDlg::RecvProc(LPVOID lpParameter)
{
SOCKET socket = ((RECVPARAM*)lpParameter)->socket;
HWND hWnd = ((RECVPARAM*)lpParameter)->hWnd;//窗口句柄
SOCKADDR_IN addrRecv;
int len = sizeof(SOCKADDR);
char recvBuf[100];
char tempBuf[100];
int recvRst;
CString recvStr;
while (TRUE)
{
//接收数据
recvRst = recvfrom(socket, recvBuf, 100, 0, (SOCKADDR*)&addrRecv, &len);
if (SOCKET_ERROR == recvRst)
{
break;
}
sprintf(tempBuf, "%s 说:%s\r\n", inet_ntoa(addrRecv.sin_addr), recvBuf);
//
//recvStr += tempBuf;//这种方式更加简单不用使用消息
//
//::SetDlgItemText(hWnd, IDC_EDIT_RECV, recvStr);
//使用自定义消息的方式来对控件填充内容
::PostMessage(hWnd, WM_RECVDATA, 0, (LPARAM)tempBuf);
}
return 0;
}
5、在OnInitDialog中调用InitSocket完成套接字初始化
InitSocket();6、添加一个自定义消息响应函数
RECVPARAM *pRecvParm = new RECVPARAM();
pRecvParm->socket = m_socket;
pRecvParm->hWnd = m_hWnd;
HANDLE hThreadRecv = CreateThread(NULL, 0, RecvProc, (LPVOID)pRecvParm, 0, NULL);
CloseHandle(hThreadRecv);
#define WM_RECVDATA WM_USER+1
afx_msg LRESULT OnRecvData(WPARAM wParam,LPARAM lParam);
ON_MESSAGE(WM_RECVDATA, OnRecvData)
在类中添加OnRecvData函数
LRESULT CMFCmultithreadDlg::OnRecvData(WPARAM wParam, LPARAM lParam)7、添加发送按钮的响应函数
{
CString str((char*)lParam);
CString strTemp;
GetDlgItemText(IDC_EDIT_RECV, strTemp);
str += "\r\n";
str += strTemp;
SetDlgItemText(IDC_EDIT_RECV, str);
return true;
}
void CMFCmultithreadDlg::OnBtnSend()
{
// TODO: 在此添加控件通知处理程序代码
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, "");
}