📄 dlgudp.cpp
字号:
// DLGUDP.cpp : implementation file
//
#include "stdafx.h"
#include "Magic2410.h"
#include "DLGUDP.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// DLGUDP dialog
DLGUDP::DLGUDP(CWnd* pParent /*=NULL*/)
: CDialog(DLGUDP::IDD, pParent)
{
//{{AFX_DATA_INIT(DLGUDP)
m_RemoteHost = _T("");
m_RemotePort = 0;
m_SendStr = _T("Hello, This is 192.168.0.231.");
m_LocalPort = 0;
//}}AFX_DATA_INIT
m_RemoteHost = "192.168.0.16"; /* 默认远程主机 IP 地址 */
m_RemotePort = 1011; /* 默认远程主机端口 */
m_LocalPort = 1025; /* 默认本机端口 */
m_strRecDisp = _T(""); /* 请空接收区的显示 */
m_UDPSocket = INVALID_SOCKET; /* 本地 UDP Socket 无效 */
m_ExitThreadEvent = NULL; /* UDP 接收线程退出事件无效 */
m_ButCloseSocket.EnableWindow(FALSE); /* "关闭"按键无效 */
//UpdateData(FALSE);
}
void DLGUDP::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(DLGUDP)
DDX_Control(pDX, IDC_OPEN, m_ButOpenSocket);
DDX_Control(pDX, IDC_CLOSE_SOCKET, m_ButCloseSocket);
DDX_Text(pDX, IDC_REMOTEHOST, m_RemoteHost);
DDX_Text(pDX, IDC_REMOTEPORT, m_RemotePort);
DDX_Text(pDX, IDC_SENDSTR, m_SendStr);
DDX_Text(pDX, IDC_LOCALPORT, m_LocalPort);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(DLGUDP, CDialog)
//{{AFX_MSG_MAP(DLGUDP)
ON_BN_CLICKED(IDC_CLEAR_RECDISP, OnClearRecdisp)
ON_BN_CLICKED(IDC_OPEN, OnOpen)
ON_BN_CLICKED(IDC_CLOSE_SOCKET, OnCloseSocket)
ON_BN_CLICKED(IDC_SEND, OnSend)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// DLGUDP message handlers
/*******************************************************************************************
函数名称: CSerialPortDlg::OnClearRec
描 述: "清除接收缓冲区" 按键单击事件代码
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void DLGUDP::OnClearRecdisp()
{
// TODO: Add your control notification handler code here
m_strRecDisp = _T("");
CEdit *pRecvStrEdit = (CEdit*)GetDlgItem(IDC_RECEIVESTR); /* 取得控件指针 */
pRecvStrEdit->SetWindowText(m_strRecDisp); /* 在窗口显示出来 */
}
/*******************************************************************************************
函数名称: CUDPExampleDlg::OnOpen
描 述: "打开端口" 按键单击事件代码
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void DLGUDP::OnOpen()
{
// TODO: Add your control notification handler code here
WSADATA wsa;
DWORD IDThread;
if (WSAStartup(MAKEWORD(1,1), &wsa) != 0) /* WinSock 初始化 */
{
MessageBox(_T("加载套接字失败!"));
return;
}
m_UDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* 创建UDP套接字 */
if (m_UDPSocket == INVALID_SOCKET)
{
WSACleanup();
MessageBox(_T("创建套接字失败!"));
return;
}
UpdateData(TRUE);
SOCKADDR_IN localAddr;
localAddr.sin_family = AF_INET; /* 初始化本地sockaddr_in */
localAddr.sin_port = htons(m_LocalPort);
localAddr.sin_addr.s_addr = INADDR_ANY;
// 绑定地址
if (bind(m_UDPSocket, (sockaddr *)&localAddr, sizeof(localAddr)) != 0)
{
MessageBox(_T("绑定本地地址到Socket失败!"));
return;
}
DWORD ul = 1;
ioctlsocket(m_UDPSocket, FIONBIO, &ul); /* 设置非阻塞通信 */
// 初始化远程 IP 地址及端口
m_RemoteAddr.sin_family = AF_INET;
m_RemoteAddr.sin_port = htons(m_RemotePort); /* 设置远程端口 */
char charRemoteHost[255];
ZeroMemory(charRemoteHost, 255);
int len = m_RemoteHost.GetLength();
if (len > 255)
{
MessageBox(_T("输入远程IP长度超长!"));
return;
}
// 将 Unicode 字符串转换为字节
LPTSTR pStr = m_RemoteHost.GetBuffer(len);
WideCharToMultiByte(CP_ACP, 0, pStr, len, charRemoteHost, len, NULL, NULL);
DWORD ipaddress = inet_addr(charRemoteHost); /* 设置远程 IP 地址 */
if ((INADDR_NONE == ipaddress) || (0 == ipaddress))
{
MessageBox(_T("输入远程IP地址格式不正确!"));
return;
}
m_RemoteAddr.sin_addr.s_addr = ipaddress;
m_ExitThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* 创建 UDP 接收线程退出事件 */
// 创建 UDP 接收线程
HANDLE hRecvThread = CreateThread(0, 0, UdpRecvTread, this, 0, &IDThread);
if (hRecvThread == NULL)
MessageBox(_T("创建接收线程失败!"));
CloseHandle(hRecvThread);
m_ButCloseSocket.EnableWindow(TRUE); /* "关闭"按键使能 */
m_ButOpenSocket.EnableWindow(FALSE); /* "打开"按键禁止 */
}
/*******************************************************************************************
函数名称: CUDPExampleDlg::OnCloseSocket
描 述: "关闭端口" 按键单击事件代码
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void DLGUDP::OnCloseSocket()
{
// TODO: Add your control notification handler code here
if (m_ExitThreadEvent != NULL)
{
SetEvent(m_ExitThreadEvent); /* 设置接收线程退出事件, 通知线程退出 */
Sleep(1000);
CloseHandle(m_ExitThreadEvent); /* 关闭线程退出事件句柄 */
}
if (m_UDPSocket != INVALID_SOCKET)
{
if (closesocket(m_UDPSocket) == SOCKET_ERROR) /* 关闭 Socket */
{
MessageBox(_T("关闭Socket失败!"));
return;
}
m_UDPSocket = INVALID_SOCKET;
if (WSACleanup() == SOCKET_ERROR) /* 释放Socket资源 */
{
MessageBox(_T("释放Socket资源失败!"));
}
}
m_ButCloseSocket.EnableWindow(FALSE); /* "关闭"键禁止 */
m_ButOpenSocket.EnableWindow(TRUE); /* "打开"键使能 */
}
/*******************************************************************************************
函数名称: CSerialPortDlg::OnClearSend
描 述: "清除发送缓冲区" 按键单击事件代码
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void DLGUDP::OnSend()
{
// TODO: Add your control notification handler code here
int nErrorCode;
if (m_UDPSocket == NULL)
{
MessageBox(_T("本地 Socket 未打开!"));
return;
}
UpdateData(TRUE);
int sendLen = m_SendStr.GetLength(); /* 取得输入字符串长度 */
char *psendbuff = new char[sendLen];
for(int i = 0; i < sendLen;i++)
psendbuff[i] = (char)m_SendStr.GetAt(i); /* 转换为单字节字符 */
int len = sendto(m_UDPSocket, psendbuff, sendLen, 0, (sockaddr*)&m_RemoteAddr, sizeof(m_RemoteAddr));
if (len == SOCKET_ERROR )
{
MessageBox(_T("UDP数据发送失败!"));
nErrorCode = WSAGetLastError();
}
delete[] psendbuff;
}
/*******************************************************************************************
函数名称: CUDPExampleDlg::UdpRecvTread
描 述: UDP 接收线程
输入参数: LPVOID lparam: 线程参数,创建线程时传入
输出参数: 无
返 回: 0: 线程退出, 返回值没特殊含义
********************************************************************************************/
DWORD DLGUDP::UdpRecvTread(LPVOID lparam)
{
fd_set fdRead;
TIMEVAL aTime;
aTime.tv_sec = 1;
aTime.tv_usec = 0;
SOCKADDR_IN tmpAddr;
int iErrorCode;
int ret;
DLGUDP * pDlg = (DLGUDP*)lparam;
while(TRUE)
{
if (WaitForSingleObject(pDlg->m_ExitThreadEvent, 0) == WAIT_OBJECT_0)
break;
FD_ZERO(&fdRead);
FD_SET(pDlg->m_UDPSocket, &fdRead);
ret = select(0, &fdRead, NULL, NULL, &aTime);
if (ret == SOCKET_ERROR)
{
iErrorCode = WSAGetLastError();
pDlg->OnUdpError(pDlg, iErrorCode);
break;
}
if (ret > 0)
{
if (FD_ISSET(pDlg->m_UDPSocket, &fdRead)) /* 检查该socket是否是fdRead中的一员 */
{
tmpAddr.sin_family = AF_INET;
tmpAddr.sin_port = htons(pDlg->m_RemoteAddr.sin_port);
tmpAddr.sin_addr.s_addr = INADDR_ANY;
char *recvBuf = new char[1024];
int tmpRecvLen = sizeof(tmpAddr);
int recvlen = recvfrom(pDlg->m_UDPSocket, recvBuf, 1024, 0, (SOCKADDR *)&tmpAddr, &tmpRecvLen);
if ((recvlen == SOCKET_ERROR) || (recvlen == 0))
{
iErrorCode = WSAGetLastError();
pDlg->OnUdpError(pDlg, iErrorCode);
delete[] recvBuf;
break;
}
else
{
pDlg->OnUdpRecv(pDlg, recvBuf, recvlen); /* 正确接收回调函数 */
delete[] recvBuf;
}
}// end of if (FD_ISSET(pDlg->m_UDPSocket, &fdRead))
}// end of if (ret > 0)
}// end of while(TRUE)
return 0;
}
void CALLBACK DLGUDP::OnUdpError(CWnd *pWnd, int nErrorCode)
{
}
/*******************************************************************************************
函数名称: CALLBACK CUDPExampleDlg::OnUdpRecv
描 述: UDP 接收数据成功回调函数
输入参数: 无
输出参数: 无
返 回: FALSE: 失败; TRUE: 成功
********************************************************************************************/
void CALLBACK DLGUDP::OnUdpRecv(CWnd *pWnd, char *buf, int buflen)
{
CString strTmp;
DLGUDP * pDlg = (DLGUDP*)pWnd;
CEdit *pRecvStrEdit = (CEdit*)pDlg->GetDlgItem(IDC_RECEIVESTR);
/* 取得控件指针 */
for (int i = 0; i < buflen; i++)
{
strTmp.Format(_T("%c"), *buf);
pDlg->m_strRecDisp += strTmp;
buf++;
}
pRecvStrEdit->SetWindowText(pDlg->m_strRecDisp); /* 在窗口显示出来 */
}
/*******************************************************************************************
函数名称: CSerialPortDlg::OnDestroy
描 述: 对话框关闭事件处理函数
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void DLGUDP::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
OnCloseSocket();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -