程序和进程
1、操作系统用来管理进程的内核对象。内核对象也是系统用来存放关于进程的统计信息的地方。
2、地址空间。它包含所有可执行模块或DLL模块的代码和数据。它还包含动态内存分配的空间。如线程堆栈和堆分配空间。
进程
进程地址空间
线程
1、线程的内核对象,操作系统用它来对线程实施管理。内核对象也是系统用来存放线程统计信息的地方。
2、线程堆栈,它用于维护线程在执行代码时需要的所有参数和局部变量。
线程运行
互斥对象
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
The CreateMutex function creates or opens a named or unnamed mutex object.
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,
BOOL bInitialOwner,
LPCTSTR lpName
);
The WaitForSingleObject function returns when the specified object is in the signaled state or the time-out interval elapses.
To enter an alertable wait state, use the WaitForSingleObjectEx function. To wait for multiple objects, use the WaitForMultipleObjects.
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
多线程代码:
#include <windows.h>
#include <iostream.h>
// 申明
DWORD WINAPI Fun1Proc(
LPVOID lpParameter // thread data
);
DWORD WINAPI Fun2Proc(
LPVOID lpParameter // thread data
);
int index=0;
int tickets=100;
HANDLE hMutex; // 必须谁拥有谁释放,请求几次必须释放几次
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1); // 关闭句柄,并没有终止新创建的线程,只表示在主线程中对新线程的使用不感兴趣,系统递减线程引用计数。线程的销毁是在主线程退出时处理。
CloseHandle(hThread2);
/*while(index++<1000)
cout<<"main thread is running"<<endl;*/
//hMutex=CreateMutex(NULL,TRUE,NULL);
hMutex=CreateMutex(NULL,TRUE,"tickets"); // 创建一个命名的互斥对象
if(hMutex)
{
if(ERROR_ALREADY_EXISTS==GetLastError())// 该名字的互斥对象已经存在,即已有一个实例在运行。
{
cout<<"only instance can run!"<<endl;
return;
}
}
WaitForSingleObject(hMutex,INFINITE);
ReleaseMutex(hMutex);
ReleaseMutex(hMutex);
Sleep(4000);
// Sleep(10);
}
DWORD WINAPI Fun1Proc(
LPVOID lpParameter // thread data
)
{
/*while(index++<1000)
cout<<"thread1 is running"<<endl;*/
/*while(TRUE)
{
//ReleaseMutex(hMutex);
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread1 sell ticket : "<<tickets--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}*/
WaitForSingleObject(hMutex,INFINITE);
cout<<"thread1 is running"<<endl;
return 0;
}
DWORD WINAPI Fun2Proc(
LPVOID lpParameter // thread data
)
{
/*while(TRUE)
{
//ReleaseMutex(hMutex);
WaitForSingleObject(hMutex,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread2 sell ticket : "<<tickets--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}*/
WaitForSingleObject(hMutex,INFINITE);
cout<<"thread2 is running"<<endl;
return 0;
}
在MFC中使用套接字
Call this function in your CWinApp::InitInstance override to initialize Windows Sockets.
BOOL AfxSocketInit(
WSADATA* lpwsaData = NULL
);
在 Afxsock.h
private:
SOCKET m_socket;
初始化套接字
BOOL CChatDlg::InitSocket()
{
m_socket=socket(AF_INET,SOCK_DGRAM,0);
if(INVALID_SOCKET==m_socket)
{
MessageBox("套接字创建失败!");
return FALSE;
}
SOCKADDR_IN addrSock;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(6000);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
int retval;
retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
if(SOCKET_ERROR==retval)
{
closesocket(m_socket);
MessageBox("绑定失败!");
return FALSE;
}
return TRUE;
}
为了防止接受阻塞,需要使用多线程,在初始化socket后,创建线程
#define WM_RECVDATA WM_USER+1
struct RECVPARAM
{
SOCKET sock;
HWND hwnd;
};
RECVPARAM *pRecvParam=new RECVPARAM;
pRecvParam->sock=m_socket;
pRecvParam->hwnd=m_hWnd;
HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
CloseHandle(hThread);
线程函数,不使用全局函数,则使用静态函数申明:
static DWORD WINAPI RecvProc(LPVOID lpParameter);
// 接受数据线程代码:
DWORD WINAPI CChatDlg::RecvProc(LPVOID lpParameter)
{
SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;
delete lpParameter; //释放内存的操作。
SOCKADDR_IN addrFrom;
int len=sizeof(SOCKADDR);
char recvBuf[200];
char tempBuf[300];
int retval;
while(TRUE) // 死循环
{
retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);
if(SOCKET_ERROR==retval)
break;
sprintf(tempBuf,"%s说: %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
}
return 0;
}
// 接受数据的消息处理
afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);
ON_MESSAGE(WM_RECVDATA,OnRecvData)
void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
{
CString str=(char*)lParam;
CString strTemp;
GetDlgItemText(IDC_EDIT_RECV,strTemp);
str+="/r/n";
str+=strTemp;
SetDlgItemText(IDC_EDIT_RECV,str);
}
// 发送数据端代码
void CChatDlg::OnBtnSend()
{
// TODO: Add your control notification handler code here
DWORD dwIP;
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);// 取得IP地址
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,""); // 清空编辑框
}