stl,boost,thread,IOCP,socket
来源:互联网 发布:aws tensorflow ami 编辑:程序博客网 时间:2024/05/16 09:06
1> STL学习 1
2 >boost asio asio,一个跨平台的支持异步I/O的网络通讯socket库 2
3>模板 2
4>boost timer 3
5>shared_ptr 3
6>Oracle 表数据的C++存取接口 occi 3
7>多线程编程 4
8>STL例子 10
8>socket编程 22
9> IOCP编程 23
10.面向对象的static关键字(类中的static关键字) 31
1> STL学习
标准模板库 STL= standard template library STL是一些容器的集合,这些容器有list,vector,set,map等,STL也是算法和其他一些组件的集合。
STL被内建在你的编译系统中。在C++标准中,STl被组织为下面的13个头文件:<algorith>,<depue>,<function>,<iterator>,<vector>,<list>,<map>,<memeory>,<numeric>,<queue>,<set>,<stack>,<utility>
算法部分主要有头文件<algorithm>,<numeric>,<functional>组成。<algorithm>是所有STL头文件中最大的一个(尽管他很好理解),它是由一大推模板函数组成的,可以认为每个函数在很大程度上都是独立的,其中常有到的功能范围涉及到比较,交换,查找,遍历操作,复制,修改,反转,排序,合并等等。<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。<funtional>中则定义了一些模板类,可以声明函数对象。
容器
在实际的开发过程中,数据结构本身的重要性不会逊于操作于数据结构的算法的重要性,当程序中存在着对时间要求很高的部分时,数据结构的选择就显得更加重要。通过设置一些模板类,STL容器对最重要的数据结构提供了支持,这些模板的参数允许我们制定容器中的元素的数据类型,可以将我们许多重复而乏味的工作简化。
容器部分主要由头文件<vector>,<list>,<depue>,<set>,<map>,<stack>,<queue>组成。
数据结构
描述
实现头文件
向量(vector)
连续存储的元素
<vector>
列表(list)
由节点组成的双向链表,每个结点包含着一个元素
<list>
双队列(deque)
连续存储的指向不同元素的指针所组成的数组
<deque>
集合(set)
由节点组成的红黑树,每个节点都包含着一个元素,节点之间以某种作用于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序
<set>
多重集合(multiset)
允许存在两个次序相等的元素的集合
<set>
栈(stack)
后进先出的值的排列
<stack>
队列(queue)
先进先出的值的排列
<queue>
优先队列(priority_queue)
元素的次序是由作用于所存储的值对上的某种谓词决定的的一种队列
<queue>
映射(map)
由{键,值}对组成的集合,以某种作用于键对上的谓词排列
<map>
多重映射(multimap)
允许键对有相等的次序的映射
<map>
迭代器在STL中用来将计算和容器联系起来,起着一种粘合剂的作用。几乎STL提供的所有算法都是通过迭代器存取元素序列进行工作的,每一个容器都定义了其本身所有的迭代器,用以存取容器中的元素。
迭代器 部分主要由头文件<utility>,<iterator><memory>组成。<utility>是一个很小的头文件,它可以贯穿使用在STL中的几个模板的声明,<iterator>中提供了迭代器使用的许多方法,而对于<memory>的描述则十分的困难,他以不同寻常的方式为容器中的元素分配存储空间,同时也为某些算法执行期间产生的临时对象提供机制,<memeory>中的主要部分是对模板类allocator,他负责产生所有容器中的默认分配器。
C++的指针也是一种迭代器。STL可以说就是以模板为基础的一个标准库。
模板是C++ STL的一个重要的内容,STL是C++的标准库。
2 >boost asio
asio,一个跨平台的支持异步I/O的网络通讯socket库
3>模板
重载达不到的效果,模板是C++参数多态化的工具。函数模板,类模板
函数模板 remple<class T> 是函数产生器,本身不是函数,能产生多种数据类型
Temple <class T>函数模板的函数体一样
Bool bigeer(T num, T nam2)
{
If(num > num2) return ture;
Else return false;
}
bigger <int>(1 , 2);bigger <double>(1 , 2);利用temple创造了两个函数
类模板
Temple <模板参数列表>
类声明
Temple <class T>
Class Array{
Enum {size = 100};
T A[size];
Public :
T& operator[](int index){ return A[index];}
}
Array<int> ia; Array<float> fa; 参数化多态
4>boost timer
Timer位于命名空间boost,为了使用timer组件,需要包含头文件<boost/timer.hpp>
#include <boost/timer.hpp>
Using namespace boost;
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
Using namespace std;
5>shared_ptr
Shared_ptr早期叫做counted_ptr,他实现了引用计数型的智能指针,与scoped_ptr一样包装了new操作符在堆上分配的动态对象,但是可以被自由的拷贝和赋值。
Temple<class T>
Class shared_ptr{
Public : typedef T element_type;
6>Oracle 表数据的C++存取接口 occi
Oracle表数据的C/C++存取方法 OCCI
OCCI是Oracle提供的c++调用接口,全名为Oracle C++ Call Interface,在9I及其以后的版本中提供,适合于nuix/Linux/Windows
7>多线程编程
Critlcal
线程同步:时间对象(Event Objects)机制 见TCP/IP P270页
临界区对象机制,Critical Section Objects
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#define THREAD_NUM 10
static DWORD WINAPI PrintThreads(LPVOID);
//临界区对象机制,Critical Section Objects
CRITICAL_SECTION cs;//定义CRITICAL_SECTION对象
int main()
{
HANDLE hThread[THREAD_NUM];
DWORD dwThreadID[THREAD_NUM];
InitializeCriticalSection(&cs);//初始化cs对象
for (int i=0;i<THREAD_NUM;i++)
{
int isStartImmediate = 0;
/*if (i == 3)
{
isStartImmediate = CREATE_SUSPENDED;
}*/
hThread[i]=CreateThread(NULL,0,PrintThreads,(LPVOID)i,isStartImmediate,&dwThreadID[i]);
if (hThread[i])
{
printf("Thread[%d] launched successfully\n",i);
}
}
//printf("Start sleep 100,and let other thread exeute\n");
//Sleep(100);
//printf("Start sleep 100,and thread 3 execute\n");
//ResumeThread(hThread[3]);
Sleep(100);
for (int i=0;i<THREAD_NUM;i++)
{
if (hThread[i])
{
CloseHandle(hThread[i]);//调用此函数来关闭线程的句柄
hThread[i] = NULL;
}
}
DeleteCriticalSection(&cs);//在进程中的各线程结束同步操作后,进程必须调用此函数释放系统资源。
return 0;
}
DWORD WINAPI PrintThreads(LPVOID num)
{
::EnterCriticalSection(&cs);
//系统判定cs对象是否被锁定,如果没有被锁定,那么线程就可以进入
//临界区以进行共享资源的互斥访问并且同时cs被置为锁定状态;否则
//说明有线程已经在使用共享资源,调用线程将被阻塞以等待cs解锁。
for (int i=0;i<10;i++)
{
printf("Thread Number is %d%d%d\n",num,num,num);
}
::LeaveCriticalSection(&cs);//在对共享资源的互斥访问结束后,线程应该调用此函数来解锁cs。
return 0;
}
//线程锁
//lock.h
#ifndef LOCK_H
#define LOCK_H
class CLock
{
public:
CLock()
{
InitializeCriticalSection(&m_lock);
}
~CLock()
{
DeleteCriticalSection(&m_lock);
}
void lock()
{
EnterCriticalSection(&m_lock);
}
void unlock()
{
LeaveCriticalSection(&m_lock);
}
private:
CRITICAL_SECTION m_lock;
};
#endif
Mutex例子
#include <iostream>
#include <Windows.h>
using namespace std;
static DWORD WINAPI Fun1Proc(LPVOID lpParameter);
static DWORD WINAPI Fun2Proc(LPVOID lpParameter);
int &tickets()
{
static int static_tickets = 10;
return static_tickets;
}
HANDLE &hMutex()
{
static HANDLE static_hMutex;
return static_hMutex;
}
int main()
{
HANDLE hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
if (hThread1)
{
printf("Thread1 launched successfully\n");
}
HANDLE hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
if (hThread2)
{
printf("Thread2 launched successfully\n");
}
hMutex() = CreateMutex(NULL,FALSE,_T("tickets"));
/*if (hMutex()&&GetLastError())
{
cout << "only one instance can run!"<<endl;
return 0;
}*/
Sleep(200);
CloseHandle(hThread1);
CloseHandle(hThread2);
return 0;
}
DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
for (;;)
{
WaitForSingleObject(hMutex(),INFINITE);
if (tickets()>0)
{
cout<<"thread1 sell ticket :"<<tickets()--<<endl;
}
else
break;
ReleaseMutex(hMutex());
}
return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
for (;;)
{
WaitForSingleObject(hMutex(),INFINITE);
if (tickets()>0)
{
cout<<"thread2 sell ticket :"<<tickets()--<<endl;
}
else
break;
ReleaseMutex(hMutex());
}
return 0;
}
放在 WaitForSingleObject后面 直到不再需要保护参数为止
如 要保护全局 int a;
线程1{
WaitforsingleObject.()...... //等待获得对a的写的权利
a++ //保护部分
ReleaseMutex()...... //不需要保护了 允许其它线程写a
}
线程2
{
WaitforsingleObject()....... //等待获得对a的写的权利
a++ //保护部分
ReleaseMutex()...... //不需要保护了 允许其它线程写a
}
MUTEX
采用互斥对象来实现多线程的同步
#include <iostream>
#include <Windows.h>
using namespace std;
DWORD WINAPI Fun1Proc(LPVOID lp);
DWORD WINAPI Fun2Proc(LPVOID lp);
int ticket = 100;
//采用互斥对象来实现多线程的同步
HANDLE hMutex;
int main()
{
HANDLE hThread1,hThread2;
hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);
hMutex = CreateMutex(NULL,FALSE,NULL);
Sleep(4000);
return 0;
}
DWORD WINAPI Fun1Proc(LPVOID lp)
{
while (TRUE)
{
WaitForSingleObject(hMutex,INFINITE);
if (ticket > 0)
{
Sleep(1);
cout << "Thread1 sell ticket : "<<ticket--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}
return 0;
}
DWORD WINAPI Fun2Proc(LPVOID lp)
{
while (TRUE)
{
WaitForSingleObject(hMutex,INFINITE);
if (ticket > 0)
{
Sleep(1);
cout << "Thread2 sell ticket : "<<ticket--<<endl;
}
else
break;
ReleaseMutex(hMutex);
}
return 0;
}
8>STL例子
#include <iostream>
#include <map>
#include <list>
#include <numeric>
using namespace std;
int main()
{
list<int> L1,L2;
for (int i=1;i<=3;i++)
{
L1.push_back(i);
L2.push_back(i+3);
}
typedef map<int,list<int>> M;
M m;
m.insert(M::value_type(1,L1));
m.insert(M::value_type(2,L2));
M::iterator It = m.begin();
list<int>::iterator Li;
while (It != m.end())
{
cout << "map "<<(*It).first<<": ";
for (Li = It->second.begin();Li != It->second.end(); Li++)
{
cout << *Li << " ";
}
cout << endl;
It++;
}
int n= m.count(3);
cout << "count of element with key '2' (0 or 1) is "<< n <<endl;
return 0;
}
True if the map is empty
#include <iostream>
#include <map>
using namespace std;
int main()
{
typedef map<int ,int>M;
M m;
m[1]=100;
m[2]=200;
m[3]=300;
cout << "values of map 'm':";
M::iterator It = m.begin();
while (It!=m.end())
{
cout << (*It).second << " ";
It++;
}
cout <<endl;
cout << "size of map = " << m.size() << endl;
cout << "map 'm' is " << (m.empty() ? "" : "not") << " empty" << endl <<endl;
m.erase(m.begin(),m.end());
cout << "After m.erase(m.begin(),m.end()) " << endl;
cout << "size of map = " << m.size()
<< endl;
cout << "map 'm' is " << (m.empty() ?
"" : "not") << "empty" << endl <<endl;
return 0;
}
erase
#include <iostream>
#include <map>
#include <string>
using namespace std;
typedef map<string ,int ,less<string>> M;
void print (M& m)
{
M::iterator It = m.begin();
cout << "map :" <<endl;
while ( It != m.end())
{
cout << (*It).first << " - "
<< (*It).second <<endl;
It++;
}
}
int main()
{
typedef M::value_type v_t;
M m;
m.insert(v_t("AAA",1));
m.insert(v_t("BBB",2));
m.insert(v_t("CCC",3));
m["DDD"]=4;
m["EEE"]=5;
print(m);
//remove element with key 'BBB'
m.erase("BBB");
print(m);
M::iterator It;
It = m.find("DDD");
// remove element pointed by It
m.erase(It);
print(m);
It = m.find("CCC");
// remove the range of elements
m.erase(m.begin(),++It);
print(m);
return 0;
}
Find
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
typedef map<int,char> M;
char ch = 'A';
M m;
for (int i=0; i<5; i++)
{
m[i] = ch++;
}
M::iterator It = m.begin();
cout << "map m :"<<endl;
while (It!= m.end())
{
cout << (*It).first << "-"
<< (*It).second << endl;
It++;
}
It = m.find(4);
if (It != m.end())
{
cout << "element key '4' has value "
<< (*It).second <<endl;
}
else
cout << "element key '4' not found" <<endl;
return 0;
}
Insert
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
typedef map<int,char> M;
typedef M::value_type v_t;
M m1,m2;
char ch = 'A';
for (int i=0;i<3;i++)
{
m1[i+1] = ch+i;
m2[i+4] = ch+i+3;
}
cout << "m1 :";
M::iterator It = m1.begin();
while (It != m1.end())
{
cout << (*It).first << "-" <<(*It).second << " ";
It++;
}
cout <<endl << "m2 :";
It = m2.begin();
while(It != m2.end())
{
cout << (*It).first << "-" <<(*It).second <<" ";
It++;
}
//insert new element
m1.insert(v_t(5,'E'));
It = m2.find(6);
//insert element pointed by It
m1.insert(*It);
cout << endl<< "m1 :" ;
It = m1.begin();
while (It != m1.end())
{
cout << (*It).first << "-" <<(*It).second <<" ";
It++;
}
m1.insert(m2.begin(),m2.end());
cout<<endl << "m1 :" ;
It = m1.begin();
while (It != m1.end())
{
cout << (*It).first << "-" <<(*It).second <<" ";
It++;
}
return 0;
}
Multimap
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
typedef multimap<int,char ,less<int>> M;
M m1;
m1.insert(M::value_type(2,'B'));
m1.insert(M::value_type(3,'C'));
m1.insert(M::value_type(1,'A'));
m1.insert(M::value_type(1,'a'));
M::iterator It = m1.begin();
cout << endl << "m1:" <<endl;
while (It != m1.end())
{
cout << (*It).first << " - "<<(*It).second <<endl;
It++;
}
return 0;
}
9》OTL编程
#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <windows.h>
#include <string>
#include "../kl_memcached/evbuffer.h"
#include <map>
#define OTL_ORA9I
#define OTL_UNICODE
#include "otlv4.h"
otl_connect db;
using namespace std;
typedef map<int,string> M;
M m_MapId;
#if _MSC_VER >= 1400
#pragma warning(disable : 4996)
#endif
//查看状态操作
void stats(SOCKET s)
{
char cmd[] = "stats\r\n";
int ret = send(s, cmd, strlen(cmd), 0);
if (ret > 0)
{
char stat_info[512];
ret = recv(s, stat_info, sizeof(stat_info)-1, 0);
if (ret > 0)
{
stat_info[ret] = 0;
printf("%s\n", stat_info);
}
}
}
//删除所有数据
void flush_all(SOCKET s)
{
char cmd[] = "flush_all\r\n";
int ret = send(s, cmd, strlen(cmd), 0);
if (ret > 0)
{
char res[256];
ret = recv(s, res, sizeof(res)-1, 0);
if (ret > 0)
{
res[ret]=0;
printf("flush_all response : %s\n",res);
}
}
}
//存储操作
void test_store(SOCKET s, const char *store_type, const char *key, const void *data,size_t size,size_t exp_time)
{
char cmd[256];
char res[256];
int ret;
sprintf_s(cmd, 256, "%s %s 0 %d %d\r\n", store_type, key,exp_time,size);
ret = send(s, cmd, strlen(cmd), 0);
if (ret>0)
{
ret = send(s,(const char*)data,size,0);
//ret = send(s,data,size,0);
ret = send(s, "\r\n", 2, 0);
ret = recv(s, res, sizeof(res)-1, 0);
if( ret > 0 )
{
res[ret] = 0;
printf( "%s command response : %s\n", store_type, res );
}
}
}
//获取数据操作
void test_get( SOCKET s, const char *key )
{
char cmd[256];
char res[256];
int ret ;
sprintf_s( cmd,256, "get %s\r\n", key );
ret = send( s, cmd, strlen( cmd ), 0 );
if( ret > 0 )
{
ret = recv( s, res, sizeof( res ) - 1, 0 );
if( ret > 0 )
{
res[ret] = 0;
printf( "test_get response : \nkey : %s\nvalue : \n%s\n", key, res );
}
}
}
//删除操作
void test_del( SOCKET s, const char *key )
{
char cmd[256];
char res[256];
int ret;
memset(cmd, 0, 256);
sprintf_s( cmd, 256,"delete %s\r\n", key );
ret = send( s, cmd, strlen( cmd ), 0 );
if( ret > 0 )
{
ret = recv( s, res, sizeof( res ) - 1, 0 );
if( ret > 0 )
{
res[ret] = 0;
printf( "test_del response : key : %s : %s\n", key, res );
}
}
}
//加减操作
void test_inc_dec( SOCKET s, const char *cmd_type, const char *key, unsigned int value )
{
char cmd[256];
char res[256];
int ret;
sprintf_s( cmd,256, "%s %s %u\r\n", cmd_type, key, value );
ret = send( s, cmd, strlen( cmd ), 0 );
if( ret > 0 )
{
ret = recv( s, res, sizeof( res ) - 1, 0 );
if( ret > 0 )
{
res[ret] = 0;
printf( "test_inc_dec : key : %s : %s\n", key, res );
}
}
}
void WcToMb(const wchar_t* wcData,char* cData)
{
int len = 0;
if(len = WideCharToMultiByte(CP_ACP,0,wcData,-1,NULL,0,NULL,NULL))
WideCharToMultiByte(CP_ACP,0,wcData,-1,cData,len,NULL,NULL);
}
void select()
{
otl_stream o(1,"select fld_id,fld_department_name from tb_user where fld_name= '中恩'",db);
int fld_id;
wchar_t szDepartment[24];
char chDepartment[24];
memset(szDepartment,'\0',24);
//cout<<"select fld_name,fld_department_name from tb_user where fld_id = 2156"<<endl;
while (!o.eof())
{
o>>fld_id>>szDepartment;
WcToMb(szDepartment,chDepartment);
m_MapId.insert(M::value_type(fld_id,chDepartment));
}
/*M::iterator It_map = m_MapId.begin();
while (It_map != m_MapId.end())
{
cout << (*It_map).first << " - "<< (*It_map).second << endl;
It_map++;
}*/
}
int main()
{
WSADATA wsaData;
WORD wVersionReq = MAKEWORD(2, 2);
WSAStartup(wVersionReq, &wsaData);
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(11211);
addr.sin_addr.s_addr = inet_addr("192.168.1.253");
int ret = connect(s, (struct sockaddr*)&addr, sizeof(addr));
if (ret == 0)
{
printf("connect ok\n");
}
{
char data[] = "北京欢迎你";
size_t len = strlen(data);
//stats(s);
/*test_store(s,"set","TestKey", data, len, 0);
test_get(s,"TestKey");
test_del(s,"TestKey");
test_get(s,"TestKey");
test_store(s,"add","TestAdd",data,len,0);
test_get(s,"TestAdd");
test_store(s,"replace","TestAdd","Hello World",11,0);
test_get(s,"TestAdd");
test_store(s,"append","TestAdd","wally",5,0);
test_get(s,"TestAdd");*/
/*test_store(s,"set","key1","11",2,0);
test_inc_dec(s,"incr","key1",10);
test_get(s,"key1");
test_inc_dec(s,"decr","key1",20);
test_get(s,"key1");*/
//flush_all(s);
otl_connect::otl_initialize();
try
{
db.rlogon("im/im@192.168.1.253/jssbook");
select();
//test_store(s,"set","key1",(char*)m_MapId,sizeof(m_MapId),60);
M::iterator It_map = m_MapId.begin();
while (It_map != m_MapId.end())
{
//cout << (*It_map).first << " - "<< (*It_map).second << endl;
char temp[12];
memset(temp,'\0',12);
sprintf_s(temp,12,"%d",(*It_map).first);
test_store(s,"set",temp,(*It_map).second.c_str(),sizeof((*It_map).second.c_str()),3600);
test_get(s,temp);
It_map++;
}
}
catch (otl_exception& p)
{
cerr<<p.msg<<p.stm_text<<p.var_info<<endl;
}
}
db.logoff();
closesocket(s);
WSACleanup();
system("pause");
return 0;
}
8>socket编程
#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
int main()
{
WSAData wsaData;
WORD wdVision = MAKEWORD(2,2);
if (WSAStartup(wdVision,&wsaData) != 0)
{
WSACleanup();
}
int nRet = 0;
int nErr = 0;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT);
//创建socket函数来创建套接口
m_socket = socket(AF_INET,SOCK_STREAM,0);
if (m_socket == SOCKET_ERROR)
{
nErr = WSAGetLastError();
}
//将一个本地的传输层地址addr与已经创建的套接口m_socket联系起来
nRet = bind(m_socket,(sockaddr*)&addr,sizeof(addr));
if (nRet == SOCKET_ERROR)
{
nErr = WSAGetLastError();
closesocket(m_socket);
}
/*if (nRet == SOCKET_ERROR)
{
cout << "Error:"<<WSAGetLastError()<<endl;
WSACleanup();
closesocket(m_socket);
}*/
//用户进程准备接受套接口上的连接请求
nRet = listen(m_socket,5);
if (nRet == SOCKET_ERROR)
{
nErr = WSAGetLastError();
closesocket(m_socket);
}
return 0;
}
9> IOCP编程
Common.h
#pragma once
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
#define DATA_BUFSIZE 1024
#define PORT_CONNECT 9988
//自定义的数据结构,便于完成端口的使用
typedef struct _OVERLAPPELUS
{
SOCKET socket;
char InBuffer[DATA_BUFSIZE]; // 输入
OVERLAPPED ovIn;
int nOutBufIndex;
char OutBuffer[DATA_BUFSIZE]; // 输出
OVERLAPPED ovOut;
DWORD dwWritten;
}OVERLAPPELUS, *LPOVERLAPPELUS;
SocketThread.h
#pragma once
#include <iostream>
#include <stdio.h>
#include <list>
#include "common.h"
using namespace std;
class ServerSocketHand
{
public:
ServerSocketHand();
~ServerSocketHand();
//initiate server
BOOL initSocket();
//start to listening the connect request
BOOL listenSocket();
//bind local information about the server
BOOL bindSocket();
//accept player to connect the server
BOOL acceptSocket();
//set completion port event
BOOL setEvent();
//check completion port event
BOOL checkEvent();
//destroy a player's socket
BOOL destorySocket();
//receiveMessage from the players
static BOOL receiveMessage(OVERLAPPELUS *pCntx);
//send Message to the players
static BOOL sendMessage(char *sendBuffer,OVERLAPPELUS *pCntx);
//broadcast Message to all the players
BOOL broadcastMessage();
//attributes setters and getters
/*HANDLE getHCompletionPort();
void setServerSocket(SOCKET nServerSocket);
SOCKET getServerSocket();*/
//create threads to deal with IO request
BOOL CreateWorkThreads();
private:
//server's socket
SOCKET m_ServerSocket;
DWORD m_pThreadID;
DWORD m_AcceptThreadID;
//server's completion port handle
HANDLE m_hCompletionPort;
//handle of each thread created to keep connect with all the player
HANDLE m_hAcceptThreadhandle;
static DWORD WINAPI WorkThread(LPVOID lpVoid);
//SocketConnect's accept thread manage player who want to connect
static DWORD WINAPI AcceptThread(LPVOID lpVoid);
//the list lists every player connected to the server
//std::list<PlayerOnServer *> m_PlayerList;
};
IocpServer.cpp
// IocpServer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "SocketThread.h"
BOOL ServerSocketHand::initSocket()
{
int err;
WSAData wsaData;
WORD wdVision = MAKEWORD(2,2);
if ((err = WSAStartup(wdVision, &wsaData)) == SOCKET_ERROR)
{
cerr << "Failed to initiate the network"<<endl;
WSACleanup();
return FALSE;
}
if ((m_ServerSocket = socket(AF_INET,SOCK_STREAM,0)) == SOCKET_ERROR)
{
cerr << "WSASocket() failed with error " << WSAGetLastError() << endl;
return FALSE;
}
return TRUE;
}
//然后绑定本地的本地server信息并创建完成I/O端口,并建立完成端口的工作线程
BOOL ServerSocketHand::bindSocket()
{
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(PORT_CONNECT);
//绑定本地server信息
int err = bind(m_ServerSocket,(struct sockaddr *)&addr, sizeof(addr));
if (err < 0)
{
cerr << "bind() error-please check TCP/IP is correct" << endl;
closesocket(m_ServerSocket);
return FALSE;
}
listenSocket();
//创建完成I/O端口
m_hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (m_hCompletionPort == NULL)
{
cerr << "CreateIoCompletionPort() error" << endl;
return FALSE;
}
acceptSocket();
//建立工作线程
CreateWorkThreads();
return TRUE;
}
//监听本地端口信息
BOOL ServerSocketHand::listenSocket()
{
listen(m_ServerSocket, 5);
cout << "local port: " << PORT_CONNECT << endl;
return TRUE;
}
//建立接受线程,接受用户的连接请求
BOOL ServerSocketHand::acceptSocket()
{
m_hAcceptThreadhandle = CreateThread(NULL, 0, AcceptThread, this, 0, &m_AcceptThreadID);
return TRUE;
}
//接受请求的工作线程,需要将新接收到的用户与建立的完成端口绑定起来
DWORD WINAPI ServerSocketHand::AcceptThread(LPVOID lpVoid)
{
ServerSocketHand *server = (ServerSocketHand*)lpVoid;
SOCKET newSocket;
OVERLAPPELUS pKey;
sockaddr_in addr;
int len = sizeof(addr);
//使用无限循环来接受用户的连接请求
while (true)
{
if ((newSocket = accept(server->m_ServerSocket,(struct sockaddr*)&addr,&len)) == SOCKET_ERROR)
{
cerr << "accept() failed with error " << WSAGetLastError() << endl;
//closesocket(newSocket);
continue;
}
//创建事件来捕获用户对服务器的请求状态
pKey.socket = newSocket;
pKey.ovOut.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
pKey.ovOut.hEvent = (HANDLE)((DWORD)pKey.ovOut.hEvent | 0x1);
//将事件与完成端口绑定,并进行第一次的数据接收
CreateIoCompletionPort((HANDLE)newSocket, server->m_hCompletionPort,(DWORD)&pKey, 0);
ServerSocketHand::receiveMessage(&pKey);
}
}
//建立一些完成端口的工作线程
BOOL ServerSocketHand::CreateWorkThreads()
{
SYSTEM_INFO SystemInfo;
GetSystemInfo(&SystemInfo);
for (int i=0; i<(int)SystemInfo.dwNumberOfProcessors*2; i++)
{
HANDLE ThreadHandle;
ThreadHandle = CreateThread(NULL, 0, WorkThread, this, 0, &m_pThreadID);
if (ThreadHandle == NULL)
{
cerr << "CreateThread() failed!" << endl;
}
CloseHandle(ThreadHandle);
}
return TRUE;
}
//工作线程
DWORD WINAPI ServerSocketHand::WorkThread(LPVOID lpVoid)
{
BOOL bResult;
DWORD dwNumRead;
struct _OVERLAPPELUS *pCntx;
LPOVERLAPPED lpOverlapped = NULL;
ServerSocketHand *server = (ServerSocketHand*)lpVoid;
UNREFERENCED_PARAMETER(lpVoid);
while (true)
{
//检查所绑定的socket的状态
bResult = GetQueuedCompletionStatus(server->m_hCompletionPort,&dwNumRead,(DWORD*)&pCntx,&lpOverlapped,INFINITE);
//根据用户对server请求的不同事件进行相应处理
if (bResult == FALSE && lpOverlapped == NULL)
{
cerr << "WorkerThread - GetQueuedCompletionStatus() error " << WSAGetLastError()<< endl;
SetLastError(0);
}
else if (bResult == FALSE && lpOverlapped != NULL)
{
cerr << "player quit abnormally" << endl;
}
else if (dwNumRead == 0)
{
cout << "player has exited" << endl;
cout << "-------------------" << endl;
}
else
{
cout << "recv data from client: " << pCntx->InBuffer << endl;
ServerSocketHand::sendMessage(pCntx->InBuffer,pCntx);
ServerSocketHand::receiveMessage(pCntx);
}
}
ExitThread(0);
return 0;
}
//接收消息的函数
BOOL ServerSocketHand::receiveMessage(OVERLAPPELUS *pCntx)
{
DWORD RecvBytes;
DWORD Flags = 0;
WSABUF DataBuff;
if (pCntx == NULL)
{
return FALSE;
}
memset(pCntx->InBuffer, 0, sizeof(pCntx->InBuffer));
ZeroMemory(&(pCntx->ovIn), sizeof(OVERLAPPED));
DataBuff.len = DATA_BUFSIZE;
DataBuff.buf = pCntx->InBuffer;
if (WSARecv(pCntx->socket,&DataBuff,1,&RecvBytes,&Flags,&(pCntx->ovIn),NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != ERROR_IO_PENDING)
{
cerr << "WSARecv() failed with error " << WSAGetLastError() << endl;
return FALSE;
}
}
return TRUE;
}
//发送消息的函数如下(static成员)
BOOL ServerSocketHand::sendMessage(char *sendBuffer,OVERLAPPELUS *pCntx)
{
DWORD SendBytes;
WSABUF DataBuff;
int len;
strcpy_s(pCntx->OutBuffer,sendBuffer);
len = strlen(pCntx->OutBuffer);
pCntx->OutBuffer[len] = '\0';
pCntx->nOutBufIndex = strlen(pCntx->OutBuffer);
DataBuff.len = len;
DataBuff.buf = pCntx->OutBuffer;
if (WSASend(pCntx->socket, &DataBuff,1,&SendBytes, 0, &(pCntx->ovOut), NULL) == SOCKET_ERROR)
{
cerr << "WSASend() failed with error " << WSAGetLastError() << endl;
return FALSE;
}
return TRUE;
}
ServerSocketHand::ServerSocketHand()
{
}
ServerSocketHand::~ServerSocketHand()
{
closesocket(m_ServerSocket);
}
int _tmain(int argc, _TCHAR* argv[])
{
ServerSocketHand SerSock;
SerSock.initSocket();
SerSock.bindSocket();
system("pause");
return 0;
}
GetQueuedCompletionStatus(
comPort, //已经创建,并且绑定了客户端套接字,的完成端口[句柄] --指定句柄
&dwIOsize, //本次传输数据的大小 --系统提取并返回给我们的变量
(LPWORD)&pClient, //完成键指针,注意:这里是在完成端口与客户端套接字绑定时的第三个参数 --系统提取并返回给我们的变量
(LPOVERLAPPED*)&lpOver, //通过该参数得到本次系统操作的结果。 --系统返回给我们的变量
INFINITE); //检测数据的时间段。超时,还是直到有数据才返回。
10.面向对象的static关键字(类中的static关键字)
1.类的静态数据成员
#include <iostream>
using namespace std;
class Mycalss
{
public:
Mycalss(int a, int b, int c);
void GetSum();
private:
int a,b,c;
static int Sum;//声明静态数据成员
};
int Mycalss::Sum = 0;//定义并初始化静态数据成员
/*
静态数据成员是该类的所有对象所共有的。对于类的多个对象来说,
静态成员只分配一次内存,供所有对象共用。
非静态数据成员,每个类对象都有自己的拷贝。
*/
Mycalss::Mycalss(int a, int b, int c)
{
this->a = a;
this->b = b;
this->c = c;
Sum += a+b+c;
}
void Mycalss::GetSum()
{
cout << " Sum = " << Sum << endl;
}
void main()
{
Mycalss M(1,2,3);
M.GetSum();
Mycalss N(4,5,6);
N.GetSum();
M.GetSum();
}
对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象被定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。也就是说,静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;
静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对于一个存款类,每个实例的利息都是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,所以节省存储空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了;
1 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性;
2 可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能;
2、静态成员函数
#include <iostream>
using namespace std;
class Mycalss
{
public:
Mycalss(int a, int b, int c);
static void GetSum();//声明静态成员函数
private:
int a,b,c;
static int Sum;//声明静态数据成员
};
int Mycalss::Sum = 0;//定义并初始化静态数据成员
/*
静态数据成员是该类的所有对象所共有的。对于类的多个对象来说,
静态成员只分配一次内存,供所有对象共用。
非静态数据成员,每个类对象都有自己的拷贝。
*/
Mycalss::Mycalss(int a, int b, int c)
{
this->a = a;
this->b = b;
this->c = c;
Sum += a+b+c;//非静态成员函数可以访问静态数据成员
}
void Mycalss::GetSum()//静态成员函数的实现
{
//cout << a << endl;//错误代码,a 是非静态数据成员
cout << " Sum = " << Sum << endl;
//静态成员函数不能访问非静态成员函数和非静态数据成员
}
void main()
{
Mycalss M(1,2,3);
M.GetSum();
Mycalss N(4,5,6);
N.GetSum();
Mycalss::GetSum();
}
- stl,boost,thread,IOCP,socket
- socket IOCP
- Socket iocp
- Boost::thread 用法(网络socket引用)TCPIP编程
- BOOST THREAD
- boost-thread
- boost::thread
- Boost Thread
- boost - thread
- Boost Thread
- boost::thread
- boost::thread
- boost thread
- boost::thread
- boost::thread
- boost::thread
- boost::thread
- Boost.Thread
- delphi编辑器功能
- 呼叫监听 android
- XML 与 Java 技术: 用 Castor 进行数据绑定
- J2XB v1.1发布:Java数据绑定框架
- JavaBean与GUI组件数据绑定模型
- stl,boost,thread,IOCP,socket
- KVM虚拟机
- Android系统源代码情景分析:基础知识
- OpenJPA
- 字符串处理函数:识别一字符串所属的数值常量类型(十六进制、二进制、十进制整数,浮点数)
- jquery一些 事件的用法
- ISDN
- 轻松搞死linux,介绍/proc/sysrq-trigger的强大功能
- 用Visual C++操作INI文件