用UDP做局域网的套接字通讯,有很多优势,
但是网上很多介绍都是关于TCP监听机制,用UDP的 都是透过创建线程或者While循环或者SetTimmer
如下例子是透过WAAsyncSelect来监听是否有FD_READ,FD_CLOSE等事件;
1.包含头文件
#include <afxsock.h> // MFC 套接字扩展
2.定义全局变量和自定义函数:
SOCKET m_Socket;//定义SOCKET套接字
BOOL Read(void);//自定义一个接收信息的函数
BOOL Send(CString sIP, u_short nPort, CString sSendData);//自定义 发送函数
3.创建一个按钮,按钮的响应函数里进行创建套接字等动作:
m_Socket = INVALID_SOCKET;
if ((m_Socket=socket(AF_INET, SOCK_DGRAM,0))== INVALID_SOCKET)
{
AfxMessageBox("创建套接字失败!");
}
SOCKADDR_IN m_saAddr;
u_short m_nPort = 20049;// 端口号
ZeroMemory(&m_saAddr, sizeof(m_saAddr));
m_saAddr.sin_family = AF_INET;
m_saAddr.sin_port= htons(m_nPort); // 如果此值为0,系统将随机选择一个未被使用的端口号
m_saAddr.sin_addr.s_addr = INADDR_ANY; // 填入本机IP地址
if (bind(m_Socket, (LPSOCKADDR) &m_saAddr, sizeof(m_saAddr)) == SOCKET_ERROR)
{
AfxMessageBox("绑定端口失败!");
}
if (WSAAsyncSelect(m_Socket, m_hWnd, WM_NETWORK_EVENT, FD_READ|FD_CLOSE|) == SOCKET_ERROR)
{
AfxMessageBox("注册网络事件失败!");
}
4.自定义Windows消息的响应函数:
afx_msg LRESULT OnNetworkEvent(WPARAM wParam, LPARAM lParam);
5.自定义一个消息链接:
BEGIN_MESSAGE_MAP(CMFCApplication4Dlg, CDialogEx) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_BUTTON1, &CMFCApplication4Dlg::OnBnClickedButton1) ON_MESSAGE(WM_NETWORK_EVENT,&C****Dlg::OnNetworkEvent) END_MESSAGE_MAP()
6.响应消息的自定义函数的定义:7.自定义的函数:LRESULT CMFCApplication4Dlg::OnNetworkEvent(WPARAM wParam, LPARAM lParam) { switch (WSAGETSELECTEVENT(lParam)) { case FD_READ: Read(); if(!Send("127.0.0.1",6000,"600")) AfxMessageBox("No"); break; case FD_ACCEPT: break; } return 0L; }
BOOL Read(void) { int nBytesRead; int nBufferLength; int nEnd; int nSpaceRemaining; char chIncomingDataBuffer[4096]; SOCKADDR_IN m_saFromAddr; int nLenght = sizeof(m_saFromAddr); ZeroMemory(&m_saFromAddr, sizeof(SOCKADDR_IN)); nEnd = 0; nBufferLength = sizeof(chIncomingDataBuffer); nSpaceRemaining = sizeof(chIncomingDataBuffer); nSpaceRemaining -= nEnd; nBytesRead = recvfrom(m_Socket, (LPSTR) (chIncomingDataBuffer + nEnd), nSpaceRemaining, 0, (LPSOCKADDR) &m_saFromAddr, &nLenght); nEnd += nBytesRead; if (nBytesRead == SOCKET_ERROR) { AfxMessageBox("读取数据出错!"); return FALSE; } // IP地址:inet_ntoa(m_saFromAddr.sin_addr); // 端口号:ntohs(m_saFromAddr.sin_port); chIncomingDataBuffer[nEnd] = '\0'; if (lstrlen(chIncomingDataBuffer) != 0) { AfxMessageBox(chIncomingDataBuffer); } return TRUE; } BOOL Send(CString sIP, u_short nPort, CString sSendData) { sSendData+='\0'; DWORD dwIP; SOCKADDR_IN saAddr; if (m_Socket == INVALID_SOCKET) { AfxMessageBox("套接字不可用!"); return FALSE; } if ((dwIP = inet_addr(sIP)) == INADDR_NONE) { AfxMessageBox("无法获取目标IP!"); return FALSE; } saAddr.sin_family = AF_INET; saAddr.sin_port= htons(nPort); saAddr.sin_addr.s_addr = dwIP; if (sendto(m_Socket, sSendData, sSendData.GetLength(), 0, (LPSOCKADDR) &saAddr, sizeof(saAddr)) == SOCKET_ERROR) { AfxMessageBox("发送数据失败!"); return FALSE; } return TRUE; }