WinSocketTest 2.0
在VS下建一个对话框的MFC程序UDPChat,去掉所有带的控件。加入以下控件:
按钮一个 IDC_BTN_SEND
编程框三个 IDC_EDIT_PORT(端口号),IDC_EDIT_REC(显示接收到的消息),IDC_EDIT_SEND(输入发送内容)
IP控件一个 IDC_IPADDRESS1
UDPChatDlg.h中加入
#define WM_RECDATA WM_USER+1
来定义一个消息号,用来处理接收到消息的事件
然后是以下方法声明:
消息映射里加入两条:
ON_MESSAGE(WM_RECDATA, OnRecData)//处理收到消息事件
ON_BN_CLICKED(IDC_BTN_SEND, &CTcpChatDlg::OnBnClickedBtnSend)//处理按钮点击事件
至此,万事具备,只欠东风。
首先窗口初始化函数OnInitDialog里加入
按钮一个 IDC_BTN_SEND
编程框三个 IDC_EDIT_PORT(端口号),IDC_EDIT_REC(显示接收到的消息),IDC_EDIT_SEND(输入发送内容)
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();
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)//处理按钮点击事件
至此,万事具备,只欠东风。
首先窗口初始化函数OnInitDialog里加入
//
构造一个新线程用于监听接收
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 " ));
后面就是四个相关的成员函数,需要注意的是在线程必须使用静态函数或者全局函数,因为这程序一开始,线程就运行起来了,而成员方法在那个时候可能还没有生成出来。
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 " ));
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创建失败 " ));
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);
// 发送消息
::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);
// 创建发送地址信息
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);
}
{
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创建失败 " ));
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);
// 发送消息
::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);
// 创建发送地址信息
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);
}