INTERNET编程之异步套接字

今天,我们看看如何使用异步套接字.我们这里用的是一个基于对话框应用程序.(UDP) .

首先,我们在对话框里添加一个SOCKET变量:(构造函数中:m_SrvSocket = INVALID_SOCKET)

SOCKET m_SrvSocket;

然后,我们在对话框的OnInitDialog中创建套接字:

BOOL CMFCSocketDlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // Add "About..." menu item to system menu.

 // IDM_ABOUTBOX must be in the system command range.
 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 ASSERT(IDM_ABOUTBOX < 0xF000);

 CMenu* pSysMenu = GetSystemMenu(FALSE);
 if (pSysMenu != NULL)
 {
  CString strAboutMenu;
  strAboutMenu.LoadString(IDS_ABOUTBOX);
  if (!strAboutMenu.IsEmpty())
  {
   pSysMenu->AppendMenu(MF_SEPARATOR);
   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  }
 }

 // Set the icon for this dialog.  The framework does this automatically
 //  when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE);   // Set big icon
 SetIcon(m_hIcon, FALSE);  // Set small icon
 
 // TODO: Add extra initialization here
 char buffer[MAX_PATH] = {0};
 m_SrvSocket = socket( AF_INET, SOCK_DGRAM, 0 );  //创建套接字
 
 SOCKADDR_IN server;
 server.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    
 server.sin_family   = AF_INET;
 server.sin_port    = htons(4443);
 
 if( SOCKET_ERROR == bind( m_SrvSocket, (SOCKADDR*)&server, sizeof(SOCKADDR) ) )
 {
  sprintf( buffer, "绑定套接字失败!错误原因:%d", WSAGetLastError() );
  MessageBox( buffer );
  closesocket( m_SrvSocket );
  PostQuitMessage(0);
 }

 if( SOCKET_ERROR == WSAAsyncSelect( m_SrvSocket, m_hWnd, WM_SOCKET_MSG, FD_READ |FD_WRITE ) )
 {
  sprintf( buffer, "选择非阻塞模式失败!错误原因:%d", WSAGetLastError() );
  MessageBox( buffer );
  closesocket( m_SrvSocket );
  PostQuitMessage(0);
 }

 return TRUE;  // return TRUE  unless you set the focus to a control
}

接着,我们在响应WM_DESTROY消息:

void CMFCSocketDlg::OnDestroy()
{
 CDialog::OnDestroy();
 
 // TODO: Add your message handler code here
 if ( m_SrvSocket != INVALID_SOCKET )
 {
  closesocket( m_SrvSocket );
  m_SrvSocket = INVALID_SOCKET;
 }
}

最后,自定义消息,如果你不会的话.我就狂晕了.这里是自定义消息的实现.

void CMFCSocketDlg::OnSocketMsg( WPARAM wParam,LPARAM lParam )
{
 UpdateData();

 CString  strString = _T("");
 char  buffer[MAX_PATH] = {0};

 SOCKADDR_IN addr;
 HOSTENT * pHost = NULL;
 int   nLen;
 int   nRet;

 nLen = sizeof(SOCKADDR);

 switch( LOWORD( lParam ) )
 {
 case FD_READ:
  do
  {
   memset( buffer, 0, MAX_PATH );
   nRet = recvfrom( m_SrvSocket , buffer, MAX_PATH - 1, 0, (SOCKADDR*)&addr, &nLen );
   if( SOCKET_ERROR == nRet )
   {
    sprintf( buffer, "接收数据失败!错误原因:%d", WSAGetLastError() );
    MessageBox( buffer );
    return ;
   }

   strString += buffer;
   if ( strstr( buffer, "/t/t/t/t" ) != NULL )
   {
    strString.Replace( _T("/t/t/t/t"), _T("/r/n" ) );
    break;
   }
  } while( TRUE );
  
  memset( buffer, 0, MAX_PATH );
  pHost = gethostbyaddr( (char*)&addr.sin_addr.S_un.S_addr, 4, AF_INET );
  sprintf( buffer, "%s:/r/n", pHost->h_name );
  m_strString = m_strString + buffer + strString;
  break;
 case FD_WRITE:
  if ( m_strHost.GetLength() <= 0  )
  {
   MessageBox( _T("请填写主机地址!") );
   return ;
  }
  if ( m_strSend.GetLength() <= 0 )
  {
   MessageBox( _T("发送消息不能为空!") );
   return ;
  }
  pHost = gethostbyname( m_strHost );
  if ( !pHost )
  {
   sprintf( buffer, "无法解析服务器地址!错误原因:%d", WSAGetLastError() );
   MessageBox( buffer );
   return ;
  }
  
  addr.sin_addr.S_un.S_addr = *((DWORD*)pHost->h_addr_list[0]);
  addr.sin_family    = AF_INET;
  addr.sin_port    = htons(4443);
  memset( addr.sin_zero, 0, sizeof(addr.sin_zero) );
  
  m_strSend += "/t/t/t/t";
  nRet = sendto( m_SrvSocket, m_strSend, m_strSend.GetLength() + 1, 0, (SOCKADDR*)&addr, nLen );
  if( SOCKET_ERROR == nRet )
  {
   sprintf( buffer, "发送数据失败!错误原因:%d", WSAGetLastError() );
   MessageBox( buffer );
   return;
  }
  m_strSend = _T("");
  break;
 }

 GetDlgItem(IDC_EDIT_SEND)->SetFocus();
 UpdateData(FALSE);
}

好了,一切搞定.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值