#include
#include
DWORD WINAPI fun1(LPVOID lpParameter);
DWORD WINAPI fun2(LPVOID lpParameter);
int tickets = 100;
CRITICAL_SECTION g_cs;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
hThread1 = CreateThread(NULL,0,fun1,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,fun2,NULL,0,NULL); //第四个参数可以来传递变量从主线程进入到fun线程。
CloseHandle(hThread1);//关掉线程句柄,不是关掉线程本身。
CloseHandle(hThread2);
InitializeCriticalSection(&g_cs);
Sleep(1000);
DeleteCriticalSection(&g_cs);
}
DWORD WINAPI fun1(LPVOID IpParameter)
{
while(TRUE)
{
EnterCriticalSection(&g_cs);
if (tickets >0)
{
cout<<"thread1 sell ticket : "<0)
{
cout<<"thread2 sell ticket : "<
如上程序,在主线程里面定义两个线程,分别从fun1和fun2开始执行。线程是利用时间片来共享一个CPU时间的,因为CPU运行速度够快,所以我们认为两个线程是并行执行的。然后利用关键代码段来实现进程互斥。对于一个全局变量来说,在各个进程中都有被用到,需要在A进程用到的时候,其他进程不能使用,不然变量就乱了。
在A进程中使用
EnterCriticalSection(&g_cs);
进入关键代码段,当其他进程遇到同样的EnterCriticalSection(&g_cs);时候,会等待g_cs的释放。所以其他进程就进入等待状态。
然后A进程使用完全局变量。释放g_cs
LeaveCriticalSection(&g_cs);
用VC MFC写的一个使用socket接受图片,然后显示图片两个进程。
其中使用一个ALL_BUFFER结构的全局变量来连接两个进程,使用关键代码段来保持这两个进程的互斥。
ALL_BUFFER结构中有100个指向char的指针,当然这个100可以更改。
当接受到图片后,把当前图片保存在的buffer复制到ALL_BUFFER的第一个指针去,然后来更多就都存进去。
然后另外一个线程从这个ALL_BUFFER中取出buffer显示出来。
所以简单来说就是一个线程只管接受,一个线程只管显示。公用一个char*型的数组(栈)。
这也达到了数据缓存的效果。
// Client_MuliThereadDlg.h : header file
//
#pragma once
struct RECVPARAM
{
SOCKET sock;
HWND hwnd;
};
struct a_buffer_size
{
char* a_buffer;
int size;
};
struct ALL_BUFFER
{
a_buffer_size ABUFFERSIZE[100];
int bufferPos;
ALL_BUFFER()
{
bufferPos = 0;
}
};
// CClient_MuliThereadDlg dialog
class CClient_MuliThereadDlg : public CDialog
{
// Construction
public:
CClient_MuliThereadDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_CLIENT_MULITHEREAD_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOk();
public:
BOOL InitSock(void);
private:
SOCKET m_socket;
public:
static DWORD WINAPI CClient_MuliThereadDlg::dataRecv(LPVOID IpParameter);
public:
static DWORD WINAPI CClient_MuliThereadDlg::dataDisp(LPVOID IpParameter);
};
// Client_MuliThereadDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Client_MuliTheread.h"
#include "Client_MuliThereadDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CClient_MuliThereadDlg dialog
//int maxBuffer = 10240000;
CRITICAL_SECTION g_cs;
ALL_BUFFER aBuffer;
CClient_MuliThereadDlg::CClient_MuliThereadDlg(CWnd* pParent /*=NULL*/)
: CDialog(CClient_MuliThereadDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CClient_MuliThereadDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CClient_MuliThereadDlg, CDialog)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// CClient_MuliThereadDlg message handlers
BOOL CClient_MuliThereadDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// 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
InitSock();
RECVPARAM *pRecvParam1 = new RECVPARAM;
RECVPARAM *pRecvParam2 = new RECVPARAM;
pRecvParam1->sock =m_socket;
pRecvParam1->hwnd =m_hWnd;
pRecvParam2 = pRecvParam1;
HANDLE mThread1 = CreateThread(NULL,0,dataRecv,(LPVOID)pRecvParam1,0,NULL);
HANDLE mThread2 = CreateThread(NULL,0,dataDisp,(LPVOID)pRecvParam2,0,NULL);
CloseHandle(mThread1);
CloseHandle(mThread2);
InitializeCriticalSection(&g_cs);
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CClient_MuliThereadDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CClient_MuliThereadDlg::OnQueryDragIcon()
{
return static_cast(m_hIcon);
}
void CClient_MuliThereadDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
DeleteCriticalSection(&g_cs);
OnOK();
}
BOOL CClient_MuliThereadDlg::InitSock(void)
{
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
//SOCKET m_socket;
m_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("163.180.117.229");
service.sin_port = htons( 6000 );
if ( bind( m_socket, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) {
closesocket(m_socket);
return FALSE;
}
listen( m_socket, SOMAXCONN );
return TRUE;
}
DWORD WINAPI CClient_MuliThereadDlg::dataRecv(LPVOID IpParameter)
{
SOCKET sock = ((RECVPARAM*)IpParameter)->sock;
//HWND hwnd = ((RECVPARAM*)IpParameter)->hwnd;
//HDC hdc = ::GetDC(hwnd);
SOCKET AcceptSocket;
SOCKADDR_IN serverInfo;
int len = sizeof(SOCKADDR);
AcceptSocket = accept(sock , (SOCKADDR*)&serverInfo, &len);
int flag = 1;
int PackteSize = 1024;
int PacketCount,LastDataPacket;
int lSzie;
char* recvbuf;
char* buffer_last;
char* buffer;
char recvbuf_count[10];
char recvbuf_last[6];
char temp[10];
int pos;
int bytesRecv,num;
int bytesRecv_count,bytesRecv_last;
// int test;
int pos_temp;
recvbuf = (char*)malloc(sizeof(char)*(PackteSize+10));
while(1)
{
bytesRecv_count = recv(AcceptSocket,recvbuf_count,10,0);
if ( bytesRecv_count == 0 )
break;
PacketCount = atoi(recvbuf_count);
//receive the LastDataPacket
bytesRecv_last = recv(AcceptSocket,recvbuf_last,6,0);
LastDataPacket = atoi(recvbuf_last);
lSzie = PackteSize * PacketCount + LastDataPacket;
buffer_last = (char*)malloc(sizeof(char)*(LastDataPacket+10));
buffer = (char*)malloc(sizeof(char)*lSzie);
int iRecvSize;
int iRet;
int idx;
int i;
for (i=0;i 0)
{
iRet = recv(AcceptSocket, recvbuf+idx, iRecvSize, 0);
if (iRet > 0)
{
idx += iRet;
iRecvSize -= iRet;
}
else if (iRet == 0)
{
break;
}
else if ( iRet == SOCKET_ERROR)
{
break;
}
}
memcpy(temp,recvbuf,10);
pos = atoi(temp);
memcpy(buffer+pos,recvbuf+10,PackteSize);
}
iRecvSize = LastDataPacket + 10;
idx = 0;
while (iRecvSize > 0)
{
iRet = recv(AcceptSocket, buffer_last+idx, iRecvSize, 0);
if (iRet > 0)
{
idx += iRet;
iRecvSize -= iRet;
}
else if (iRet == 0)
{
break;
}
else if ( iRet == SOCKET_ERROR)
{
break;
}
}
memcpy(temp,buffer_last,10);
pos = atoi(temp);
memcpy(buffer+pos,buffer_last+10,LastDataPacket);
EnterCriticalSection(&g_cs);
pos_temp = aBuffer.bufferPos;
aBuffer.ABUFFERSIZE[pos_temp].a_buffer = (char*)malloc(sizeof(char)*lSzie);
memcpy(aBuffer.ABUFFERSIZE[pos_temp].a_buffer,buffer,lSzie);
aBuffer.ABUFFERSIZE[pos_temp].size = lSzie;
aBuffer.bufferPos++;
LeaveCriticalSection(&g_cs);
free(buffer_last);
free(buffer);
}
free(recvbuf);
closesocket(AcceptSocket);
WSACleanup();
return 0;
}
DWORD WINAPI CClient_MuliThereadDlg::dataDisp(LPVOID IpParameter)
{
HWND hwnd = ((RECVPARAM*)IpParameter)->hwnd;
HDC hdc = ::GetDC(hwnd);
IPicture* pPic;
IStream* pStm;
int pos_temp;
int lSzie;
char* buffer;
while(TRUE)
{
EnterCriticalSection(&g_cs);
if (aBuffer.bufferPos > 0)
{
pos_temp = aBuffer.bufferPos;
lSzie = aBuffer.ABUFFERSIZE[pos_temp-1].size;
buffer = (char*)malloc(sizeof(char)*lSzie);
memcpy(buffer,aBuffer.ABUFFERSIZE[pos_temp-1].a_buffer,lSzie);
aBuffer.bufferPos--;
free(aBuffer.ABUFFERSIZE[pos_temp-1].a_buffer);
LeaveCriticalSection(&g_cs);
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE,lSzie);
LPVOID pvData = NULL;
pvData = GlobalLock(hGlobal);
memcpy(pvData,buffer,lSzie);
GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);
ULARGE_INTEGER pSeek;
LARGE_INTEGER dlibMove ={0};
pStm->Seek(dlibMove,STREAM_SEEK_SET,&pSeek);
OleLoadPicture(pStm,lSzie,TRUE,IID_IPicture,(LPVOID*)&pPic);
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight);
pPic->Render(hdc,0,0,320,240,0,hmHeight,hmWidth,-hmHeight,NULL);
GlobalFree(hGlobal);
free(buffer);
}
else
LeaveCriticalSection(&g_cs);
}
//free(buffer);
pPic->Release();
pStm->Release();
return 0;
}