孙鑫老师VC笔记 下载本文

内容发布更新时间 : 2024/5/19 6:30:19星期一 下面是文章的全部内容请认真阅读。

{

// TOD Add your control notification handler code here DWORD dwIP;

((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP); SOCKADDR_IN addrTo; addrTo.sin_family=AF_INET; addrTo.sin_port=htons(6000);

addrTo.sin_addr.S_un.S_addr=htonl(dwIP); CString strSend;

GetDlgItemText(IDC_EDIT_SEND,strSend); sendto(m_socket,strSend,strSend.GetLength()+1,0, (SOCKADDR*)&addrTo,sizeof(SOCKADDR)); SetDlgItemText(IDC_EDIT_SEND,\}

第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\str.Format(\说 :%s\str+=\

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地址转换为主机名的功能 嘿嘿,单线程的聊天室创建完毕!性能并且非常出色!

第17课 进程间通信 有四种方法 1.剪贴板

a.创建个ClipBoard的对话框应用程序,加两EditBox和两个Button发送接收。 b.具体代码:

发送端代码: if(OpenClipboard()) {

CString str; HANDLE hClip; char *pBuf; EmptyClipboard();

GetDlgItemText(IDC_EDIT_SEND,str);

hClip=GlobalAlloc(GMEM_MOVEABLE,str.GetLength()+1); pBuf=(char*)GlobalLock(hClip);将句柄转换为指针! strcpy(pBuf,str); GlobalUnlock(hClip);

SetClipboardData(CF_TEXT,hClip); CloseClipboard(); }

接收端代码: if(OpenClipboard()) {

if(IsClipboardFormatAvailable(CF_TEXT)) {

HANDLE hClip; char *pBuf;

hClip=GetClipboardData(CF_TEXT); pBuf=(char*)GlobalLock(hClip); GlobalUnlock(hClip);

SetDlgItemText(IDC_EDIT_RECV,pBuf); CloseClipboard(); } }

2.匿名管道:只能在父子进程之间进行通信

a.先建一个Parent的单文档应用程序,增加“创建管道”“读取数据”“写入数据”三个菜单 b.增加成员变量HANDLE类型的hRead,hWrite,初始化变量,并在析构函数中释放句柄 c.响应菜单代码:

void CParentView::OnPipeCreate() 菜单“创建管道”代码 {

// TOD Add your command handler code here SECURITY_ATTRIBUTES sa; sa.bInheritHandle=TRUE;

sa.lpSecurityDescriptor=NULL;

sa.nLength=sizeof(SECURITY_ATTRIBUTES); if(!CreatePipe(&hRead,&hWrite,&sa,0)) {

MessageBox(\创建匿名管道失败!\return; }

STARTUPINFO sui;

PROCESS_INFORMATION pi;

ZeroMemory(&sui,sizeof(STARTUPINFO));将数据清0! sui.cb=sizeof(STARTUPINFO);

sui.dwFlags=STARTF_USESTDHANDLES; sui.hStdInput=hRead; sui.hStdOutput=hWrite;

sui.hStdError=GetStdHandle(STD_ERROR_HANDLE);

if(!CreateProcess(\TRUE,0,NULL,NULL,&sui,&pi))创建子进程 {

CloseHandle(hRead);

CloseHandle(hWrite);关闭句柄,将内核对象的使用计数减少1,这样当操作系统发现内核对象的使用计数为0时,将清除内核对象。 hRead=NULL; hWrite=NULL;

MessageBox(\创建子进程失败!\return; } else {

CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } }

void CParentView::OnPipeRead() 菜单“读取数据”代码 {

// TOD Add your command handler code here char buf[100]; DWORD dwRead;