本工具设计的目的是用于自己项目上,由于好久没有使用C++了,可能编程有些丑陋,哪里不对希望大家见谅。本文参考了许多前辈的例子,终于搞好了。若有和前辈们相同的地方,可以联系我,进行删除。本意也是大家互相学习嘛,废话不多说了,看图:
由于是我们项目专用的工具,端口目前是固定写死在程序中的,有需要的可以自己进行添加。
创建连接
void CMFCUDPDlg::OnClickedButtonCreateSocket()
{
// TODO: 在此添加控件通知处理程序代码
CString temp;
m_createsocket.GetWindowText(temp);///获取按钮的文本
UpdateData(true);
if(temp == _T("关闭连接"))///表示点击后是"关闭串口",也就是已经关闭了串口
{
//关闭socket
m_createsocket.SetWindowText(_T("打开连接"));///设置按钮文字为"打开串口"
//关闭接收线程,关闭socket
CloseListenTread();
closesocket(m_socket);
}
else if(temp == _T("打开连接"))///当前列表的内容个数
{
UpdateData(true);
m_socket = socket(AF_INET, SOCK_DGRAM, 0);
if( INVALID_SOCKET == m_socket )
{
AfxMessageBox(_T("创建套接字失败"));
return;
}
else
{
SOCKADDR_IN addr;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
//addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addr.sin_family = AF_INET;
addr.sin_port = htons(6000);
int retval;
retval = bind(m_socket, (SOCKADDR*)&addr, sizeof(SOCKADDR));
if (SOCKET_ERROR == retval)
{
AfxMessageBox(_T("绑定失败!"));
closesocket(m_socket);
return ;
}
//创建接收线程
if (!OpenListenThread())
{
AfxMessageBox(_T("错误,请关闭应用,重新打开!"));
}
m_createsocket.SetWindowText(_T("关闭连接"));
}
}
}
发送数据:
void CMFCUDPDlg::OnClickedButtonSendMessage()
{
// TODO: 在此添加控件通知处理程序代码
GetDlgItem(IDC_BUTTON_SEND)->SetFocus();
CString temp;
int i=0;
UpdateData(true);
m_createsocket.GetWindowText(temp);
if (temp == "打开连接")///没有打开串口
{
AfxMessageBox(_T("请首先打开连接"));
return;
}
m_sendmessage.GetWindowText(temp);
size_t len = _tcsclen(temp) + 1;
char* m_str = NULL;
size_t* converted = 0;
m_str = new char[len];
#ifdef UNICODE
wcstombs_s(converted, m_str, len, temp.GetBuffer(0), _TRUNCATE);
#else
m_str = temp.GetBuffer(0);
#endif
DWORD dwIP;
m_hostip.GetAddress(dwIP);
SOCKADDR_IN addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(hostport);
addr.sin_addr.s_addr = htonl(dwIP);
sendto(m_socket, m_str, strlen(m_str), 0, (SOCKADDR*)&addr, sizeof(SOCKADDR));
m_sendmessage.SetSel(0, -1);
m_sendmessage.Clear();//清空数据
m_sendmessage.GetFocus();//再次获得焦点
UpdateData(FALSE);//必须的。否则界面内容不更新改变
}
接收数据是放在另外一个线程中进行处理
UINT WINAPI CMFCUDPDlg::RecvThreadProc(LPVOID lpParameter)
{
//AfxMessageBox(_T("线程工作"));
/** 得到本类的指针 */
CMFCUDPDlg *pRecvMessage = reinterpret_cast<CMFCUDPDlg*>(lpParameter);
SOCKADDR_IN ClntAddr;
int clntAddrLen = sizeof(ClntAddr);
char echoBuffer[1024]="";
CString buffer;
int recvMsgSize = 0;
size_t len = 0;
size_t converted = 0;
//处理数据的接收
if(!s_bExit)//表示线程已经开启,正在工作,这句代码可以不要,下面的while有判断
{
while(!s_bExit)
{
//一直阻塞到有客户端发来数据 (sock, recvBuf, 200, 0, (SOCKADDR*)&addr, &len);
recvMsgSize = recvfrom(pRecvMessage->m_socket,echoBuffer,sizeof(echoBuffer),0 ,(SOCKADDR*)&ClntAddr, &clntAddrLen);
if (SOCKET_ERROR == recvMsgSize)
{
//AfxMessageBox(_T("断开连接,请重新打开连接"));
break;
}
//把echoBuffer转格式成wchar_t
len = strlen(echoBuffer) + 1;
wchar_t *WStr;
WStr=(wchar_t*)malloc(len*sizeof(wchar_t));
mbstowcs_s(&converted, WStr, len, echoBuffer, _TRUNCATE);
//获取对方ip
char *addr = inet_ntoa(ClntAddr.sin_addr);
//把addr转格式成wchar_t
len = strlen(addr) + 1;
wchar_t *address;
address=(wchar_t*)malloc(len*sizeof(wchar_t));
mbstowcs_s(&converted, address, len, addr, _TRUNCATE);
/*把发送端的ip地址和消息还有换行都存放在buffer里,然后一直往save里追加*/
buffer.Format(_T("【%s】说 :%s\r\n"),address,WStr);
pRecvMessage->m_recvmessage.SetSel(-1, -1);
pRecvMessage->m_recvmessage.ReplaceSel(buffer);
}
}
return 0;
}
工程代码中也有一些对线程的管理,以及对控件大小随着主对话框大小改变的处理。
下载地址:https://download.csdn.net/download/lionmon82/10732605
第一次发博客,哪里做的不好多见谅。
本文参考了前辈们的例程,若有侵权,请联系我删除。