第16课 线程同步与异步 套接字编程

1. 事件对象:来实现线程的同步。与互斥对象一样均属于内核对象。
             当人工重置有信号时,所有线程均得到信号,所以不能设为人工重置。代码就不贴了。
             通过创建匿名的事件对象,也可以让一个程序只能运行一个实例。  

2. 关键代码段实现线程的同步:类似公用电话亭,只有当电话亭里面没人了,其它人才可以再进去打电话。用了  4个函数,这种方法比较简单!但缺点是如果使用了多少关键代码码,容易赞成线程的死锁

3. 线程死锁,用关键代码示例,用了两个临界区对象,实战中要注意避免这种错误!

4. 使用异步套接字编写网络聊天室
  1) 加载套接字库,进行版本协商,包含头文件,链接库文件,这次请示的是  2.2版本!
  2 )在类 CChatDlg  中增加一个成员变量 m_socket,在析构函数中释放这个变量
  3 )利用 WSASocket()  创建套接字(数据报类型的 UDP型的)
  4 )然后调用 WSAAsyncSelect(m_socket,m_hWnd,UM_SOCK,FD_READ) 为网络事件定义消息!此时如果发生  FD_READ消息,系统会发送UM_SOCK消息给应用程序!程序并不会阻塞在这儿了!
   以上是在BOOL CChatDlg::OnInitDialog() 完成
  5 )然后完成消息响应!
   头文件中:#define UM_SOCK  WM_USER+1
 afx_msg void OnSock(WPARAM,LPARAM);
    源文件中:
    ON_MESSAGE(UM_SOCK,OnSock)
     实现消息响应函数: void CChatDlg::OnSock(WPARAM wParam,LPARAM lParam)
{
 switch(LOWORD(lParam))
 {
 case FD_READ:
  WSABUF wsabuf;
  wsabuf.buf=new char[200];
  wsabuf.len=200;
  DWORD dwRead;
  DWORD dwFlag=0;
  SOCKADDR_IN addrFrom;
  int len=sizeof(SOCKADDR);
  CString str;
  CString strTemp;
  HOSTENT *pHost;
  if(SOCKET_ERROR==WSARecvFrom(m_socket,&wsabuf,1,&dwRead,&dwFlag,
      (SOCKADDR*)&addrFrom,&len,NULL,NULL))
  {
   MessageBox("  接收数据失败! ");
   return;
  }
  pHost=gethostbyaddr((char*)&addrFrom.sin_addr.S_un.S_addr,4,AF_INET);
  //str.Format("%s   :%s",inet_ntoa(addrFrom.sin_addr),wsabuf.buf);
  str.Format("%s   :%s",pHost->h_name,wsabuf.buf);
  str+="\r\n";
  GetDlgItemText(IDC_EDIT_RECV,strTemp);
  str+=strTemp;
  SetDlgItemText(IDC_EDIT_RECV,str);
  break;
 }
}
OK
      6  )完成数据发送的功能!
      void CChatDlg::OnBtnSend()
{
 // TOD Add your control notification handler code here
 DWORD dwIP;
 CString strSend;
 WSABUF wsabuf;
 DWORD dwSend;
 int len;
 CString strHostName;
 SOCKADDR_IN addrTo;
 HOSTENT* pHost;
 if(GetDlgItemText(IDC_EDIT_HOSTNAME,strHostName),strHostName=="")
 {
  ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);
  addrTo.sin_addr.S_un.S_addr=htonl(dwIP);
 }
 else
 {
  pHost=gethostbyname(strHostName);
  addrTo.sin_addr.S_un.S_addr=*((DWORD*)pHost->h_addr_list[0]);
 }
 
 addrTo.sin_family=AF_INET;
 addrTo.sin_port=htons(6000); GetDlgItemText(IDC_EDIT_SEND,strSend);
 len=strSend.GetLength();
 wsabuf.buf=strSend.GetBuffer(len);
 wsabuf.len=len+1; SetDlgItemText(IDC_EDIT_SEND,""); if(SOCKET_ERROR==WSASendTo(m_socket,&wsabuf,1,&dwSend,0,
   (SOCKADDR*)&addrTo,sizeof(SOCKADDR),NULL,NULL))
 {
  MessageBox("  发送数据失败! ");
  return;
 }
 
}      7  )完成将主机名转换为 IP地址的功能,以前将IP地址转换为主机名的功能
嘿嘿,单线程的聊天室创建完毕!性能并且非常出色!

猜你喜欢

转载自blog.csdn.net/zhang_zxk/article/details/52401947