Sunshine Alike

半完美主义

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  35 Posts :: 1 Stories :: 56 Comments :: 0 Trackbacks

常用链接

留言簿(15)

积分与排名

  • 积分 - 48956
  • 排名 - 449

最新随笔

最新评论

  在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
来定义一个消息号,用来处理接收到消息的事件

然后是以下方法声明:
private:
    
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(127001);
    SetDlgItemText(IDC_EDIT_PORT, _T(
"6000"));
后面就是四个相关的成员函数,需要注意的是在线程必须使用静态函数或者全局函数,因为这程序一开始,线程就运行起来了,而成员方法在那个时候可能还没有生成出来。
bool CTcpChatDlg::InitSocket()
{

    WORD wVersionRequested;
    WSADATA wsaData;
    wVersionRequested 
= MAKEWORD( 22 );

    
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()
+10
        (SOCKADDR 
*)&addrTo, sizeof(addrTo)
        ))
    {
        CString strError;
        strError.FormatMessage(
"Send Failed, Error Code: %d", WSAGetLastError());
        MessageBox(strError);
    }
    
    closesocket(sock);
}

posted on 2009-05-06 17:08 Sunshine Alike 阅读(304) 评论(0)  编辑 收藏 引用 所属分类: WinAPI应用程序

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理