关键源码
/*****************************************************************************************
* @ 关闭socket
*****************************************************************************************/
#define WING_ERROR_CLOSE_SOCKET 4001
#define WING_ERROR_ACCEPT4002
#define WING_ERROR_MALLOC4003
#define WING_BAD_ERROR-4
void _close_socket( SOCKET socket){
int error_code = WSAGetLastError();
//这里偶尔也会报异常
if( 0 != closesocket(socket )){
char error_msg[32] = {0};
sprintf(error_msg,"%ld",error_code);
MessageBoxA(0,error_msg,error_msg,0);
elemType *msg= new elemType();
if( NULL == msg ) exit(WING_BAD_ERROR);
memory_add();
memory_add_bytes(sizeof(elemType));
HANDLE handle = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
msg->message_id = WM_ONERROR;
msg->wparam= 0;
msg->lparam= WING_ERROR_CLOSE_SOCKET;
msg->size= pmc.WorkingSetSize;
enQueue(message_queue,msg);
}
}
void _throw_error( int error_code ){
exit(WING_BAD_ERROR);
/*elemType *msg= new elemType();
if( NULL == msg)exit(WING_BAD_ERROR);
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONERROR;
msg->wparam= 0;
msg->lparam= error_code;
enQueue(message_queue,msg);*/
}
/*****************************************************************************************
* @ iocp工作线程
*****************************************************************************************/
unsigned int __stdcall socket_worker(LPVOID lpParams)
{
COMPARAMS *params = (COMPARAMS *)lpParams;
HANDLE ComplectionPort = params->IOCompletionPort;
DWORD thread_id = params->threadid;
DWORD BytesTransferred=0;
PER_HANDLE_DATA *PerHandleData=NULL;
PER_IO_OPERATION_DATA *PerIOData=NULL;
DWORD RecvBytes=0;
DWORD Flags=0;
HANDLE handle = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
while (TRUE)
{
BOOL wstatus = GetQueuedCompletionStatus(ComplectionPort,&BytesTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED*)&PerIOData,INFINITE);
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
unsigned int begin_size = pmc.WorkingSetSize;
//服务终止
if( BytesTransferred==-1 && PerIOData == NULL )
{
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONQUIT;
msg->wparam = 0;
msg->lparam = 0;
msg->size = begin_size;
enQueue(message_queue,msg);
_close_socket(PerHandleData->Socket);
memory_sub_bytes(sizeof(PER_HANDLE_DATA));
//memory_sub_bytes(sizeof(PER_IO_OPERATION_DATA));
delete PerHandleData;
//delete PerIOData;
PerHandleData = NULL;
PerIOData = NULL;
memory_sub();
memory_sub();
return 0;
}
int error_code = WSAGetLastError();
unsigned long _socket = (unsigned long)PerHandleData->Socket;
//掉线检测
if (BytesTransferred == 0 || 10054 == error_code || 64 == error_code || false == wstatus || 1236 == error_code)
{
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONCLOSE;
msg->wparam = _socket;
msg->lparam = 0;
msg->size = begin_size;
enQueue(message_queue,msg);
if(1236 != error_code)//服务端调用了 _close_socket 强制终止
_close_socket(PerHandleData->Socket);
memory_sub_bytes(sizeof(PER_IO_OPERATION_DATA));
memory_sub_bytes(sizeof(PER_HANDLE_DATA));
delete PerIOData;
delete PerHandleData;
PerHandleData = NULL;
PerIOData = NULL;
memory_sub();
memory_sub();
continue;
}
//收到消息
if( PerIOData->type == OPE_RECV ) {
RECV_MSG *recv_msg= new RECV_MSG();
if( NULL == recv_msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
ZeroMemory(recv_msg,sizeof(RECV_MSG));
recv_msg->msg= new char[BytesTransferred+1];
ZeroMemory(recv_msg->msg,BytesTransferred+1);
strcpy_s(recv_msg->msg,BytesTransferred+1,PerIOData->Buffer);
recv_msg->len= BytesTransferred+1;
memory_add();
memory_add();
memory_add_bytes(sizeof(RECV_MSG));
memory_add_bytes(sizeof(char)*(BytesTransferred+1));
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONRECV;
msg->wparam= _socket;
msg->lparam= (unsigned long)recv_msg;
msg->size = begin_size;
enQueue(message_queue,msg);
BytesTransferred= 0;
Flags= 0;
ZeroMemory(&(PerIOData->OVerlapped),sizeof(OVERLAPPED));
ZeroMemory(PerIOData->Buffer,DATA_BUFSIZE);
PerIOData->DATABuf.buf= PerIOData->Buffer;
PerIOData->DATABuf.len= DATA_BUFSIZE;
PerIOData->type= OPE_RECV;
int error_code = WSARecv(PerHandleData->Socket,&(PerIOData->DATABuf),1,&RecvBytes,&Flags,&(PerIOData->OVerlapped),NULL);
//接收完一次消息之后 再次调用 WSARecv 触发 iocp异步接收
//如果发生错误
if( 0 != error_code && WSAGetLastError() != WSA_IO_PENDING){
elemType *msg= new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONCLOSE;
msg->wparam= _socket;
msg->lparam= 0;
msg->size = begin_size;
enQueue(message_queue,msg);
_close_socket(PerHandleData->Socket);
memory_sub_bytes(sizeof(PER_IO_OPERATION_DATA));
memory_sub_bytes(sizeof(PER_HANDLE_DATA));
delete PerIOData;
delete PerHandleData;
PerIOData = NULL;
PerHandleData = NULL;
memory_sub();
memory_sub();
}
}
//发送消息完成
else if(PerIOData->type == OPE_SEND)
{
ZeroMemory(PerIOData,sizeof(PER_IO_OPERATION_DATA));
memory_sub_bytes(sizeof(PER_IO_OPERATION_DATA));
delete PerIOData;
PerIOData = NULL;
memory_sub();
BytesTransferred = 0;
elemType *msg= new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONSEND;
msg->wparam= _socket;
msg->lparam= 0;
msg->size= begin_size;
enQueue(message_queue,msg);
}
}
return 0;
}
//接受客户端连接进来的工作线程
unsigned int __stdcall accept_worker(LPVOID _socket) {
COMPARAMS *_data= (COMPARAMS*)_socket;
SOCKET m_sockListen= _data->Socket;
HANDLE m_hIOCompletionPort= _data->IOCompletionPort;
DWORD threadid= _data->threadid;
SOCKET accept ;
PER_HANDLE_DATA *PerHandleData = NULL;
PER_IO_OPERATION_DATA *PerIOData = NULL;
DWORD RecvBytes = 0;
DWORD Flags = 0;
HANDLE handle = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
while(true){
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
unsigned int begin_size = pmc.WorkingSetSize;
accept = WSAAccept(m_sockListen,NULL,NULL,NULL,0);
int error_code = WSAGetLastError() ;
//10024 打开了过多的套接字
if( INVALID_SOCKET == accept || 10024 == error_code ){
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONERROR;
msg->wparam = 0;
msg->lparam = WING_ERROR_ACCEPT;
msg->size = begin_size;
enQueue(message_queue,msg);
continue;
}
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONCONNECT;
msg->wparam = (unsigned long)accept;
msg->lparam = 0;
msg->size = begin_size;
enQueue(message_queue,msg);
//WM_TEST
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
int test_size = pmc.WorkingSetSize;
PerHandleData = new PER_HANDLE_DATA();
if( NULL == PerHandleData ){
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONCLOSE;
msg->wparam = (unsigned long)accept;
msg->lparam = 0;
msg->size = begin_size;
enQueue(message_queue,msg);
_close_socket(accept);
continue;
}
memory_add();
memory_add_bytes(sizeof(PER_HANDLE_DATA));
PerHandleData->Socket = accept;
HANDLE iocp = CreateIoCompletionPort ((HANDLE )accept ,m_hIOCompletionPort , (ULONG_PTR)PerHandleData ,0);
if( NULL == iocp){
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONCLOSE;
msg->wparam = (unsigned long)PerHandleData->Socket;
msg->lparam = 0;
msg->size = begin_size;
enQueue(message_queue,msg);
_close_socket(PerHandleData->Socket);
memory_sub_bytes(sizeof(PER_HANDLE_DATA));
delete PerHandleData;
memory_sub();
continue;
}
PerIOData = new PER_IO_OPERATION_DATA();
if ( NULL == PerIOData )
{
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONCLOSE;
msg->wparam = (unsigned long)PerHandleData->Socket;
msg->lparam = 0;
msg->size = begin_size;
enQueue(message_queue,msg);
_close_socket(PerHandleData->Socket);
memory_sub_bytes(sizeof(PER_HANDLE_DATA));
delete PerHandleData;
PerHandleData = NULL;
memory_sub();
continue;
}
memory_add();
memory_add_bytes(sizeof(PER_IO_OPERATION_DATA));
/* 心跳检测 暂时没有详细测试
int Opt = 1;
tcp_keepalive live,liveout;
live.keepaliveinterval=1000;
live.keepalivetime=1000; //勘误 1分钟是 60000 以此类推
live.onoff=TRUE;
int iRet = setsockopt(accept,SOL_SOCKET,SO_KEEPALIVE,(char *)&Opt,sizeof(Opt));
if(iRet != 0){
elemType *msg=(elemType*) (sizeof(elemType));
memory_add();
msg->message_id = WM_ONCLOSE;
msg->wparam = (unsigned long)PerHandleData->Socket;
msg->lparam = 0;
enQueue(message_queue,msg);
_close_socket(PerHandleData->Socket);
delete(PerHandleData);
memory_sub();
continue;
}
*/
ZeroMemory(&(PerIOData->OVerlapped),sizeof(OVERLAPPED));
ZeroMemory(PerIOData->Buffer,sizeof(PerIOData->Buffer));
PerIOData->DATABuf.len = DATA_BUFSIZE;
PerIOData->DATABuf.buf = PerIOData->Buffer;
PerIOData->type = 1;
Flags = 0;
//这个地方偶尔报异常 还没完全解决
int code = WSARecv(accept,&(PerIOData->DATABuf),1,&RecvBytes,&Flags,&(PerIOData->OVerlapped),NULL);
error_code = WSAGetLastError();
//调用一次 WSARecv 触发iocp事件
if(0 != code && WSA_IO_PENDING != error_code){
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_ONCLOSE;
msg->wparam = (unsigned long)PerHandleData->Socket;
msg->lparam = 0;
msg->size = begin_size;
enQueue(message_queue,msg);
_close_socket(PerHandleData->Socket);
memory_sub_bytes(sizeof(PER_HANDLE_DATA));
memory_sub_bytes(sizeof(PER_IO_OPERATION_DATA));
delete PerHandleData;
delete PerIOData;
PerHandleData = NULL;
PerIOData = NULL;
memory_sub();
memory_sub();
}
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return 0;
}
memory_add();
memory_add_bytes(sizeof(elemType));
msg->message_id = WM_TEST;
msg->wparam = 0;
msg->lparam = 0;
msg->size = pmc.WorkingSetSize-test_size;
enQueue(message_queue,msg);
}
return 0;
}
//iocp 服务主线程
ZEND_FUNCTION(wing_service){
InitializeCriticalSection(&bytes_lock);
zval *onreceive = NULL;
zval *onconnect = NULL;
zval *onclose = NULL;
zval *onerror = NULL;
zval *call_cycle=NULL;
zval *_params = NULL;
int port = 0;
//zval *_port;
//zval *_listen_ip;
char *listen_ip = NULL;
MAKE_STD_ZVAL(onreceive);
MAKE_STD_ZVAL(onconnect);
MAKE_STD_ZVAL(onclose);
MAKE_STD_ZVAL(onerror);
//参数获取
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z",&_params) != SUCCESS) {
RETURN_LONG(WING_ERROR_PARAMETER_ERROR);
return;
}
//如果参数不是数组
if(Z_TYPE_P(_params) != IS_ARRAY){
RETURN_LONG(WING_ERROR_PARAMETER_ERROR);
return;
}
HashTable *arr_hash = Z_ARRVAL_P(_params);
int argc= zend_hash_num_elements(arr_hash);
zval **data = NULL;
HashPosition pointer = NULL;
/*
查不到值不知为何 待测试
zend_hash_find(arr_hash,"port",strlen("port")+1,(void**)&_port);
port = Z_LVAL_P(_port);
zend_printf("%ld",port);
zend_hash_find(arr_hash,"listen",strlen("listen")+1,(void**)&_listen_ip);
listen_ip = Z_STRVAL_P(_listen_ip);
zend_printf("%s",listen_ip);
zend_hash_find(arr_hash,"onreceive",strlen("onreceive")+1,(void**)&onreceive);
zend_hash_find(arr_hash,"onconnect",strlen("onconnect")+1,(void**)&onconnect);
zend_hash_find(arr_hash,"onclose",strlen("onclose")+1,(void**)&onclose);
zend_hash_find(arr_hash,"onerror",strlen("onerror")+1,(void**)&onerror);
*/
//数组参数解析
for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS; zend_hash_move_forward_ex(arr_hash, &pointer)) {
char *key;
int key_len;
long index;
if (zend_hash_get_current_key_ex(arr_hash, &key, (uint*)&key_len, (ulong*)&index, 0, &pointer) == HASH_KEY_IS_STRING) {
if(strcmp(key,"port")==0){
port = Z_LVAL_PP(data);
}else if(strcmp(key,"listen")==0){
listen_ip = Z_STRVAL_PP(data);
}else if(strcmp(key,"onreceive")==0){
onreceive = *data;
}else if(strcmp(key,"onconnect")==0){
onconnect = *data;
}else if(strcmp(key,"onclose")==0){
onclose = *data;
}else if(strcmp(key,"onerror")==0){
onerror = *data;
}
//call_cycle
else if(strcmp(key,"call_cycle")==0){
call_cycle = *data;
}
}
}
//初始化消息队列
message_queue= new queue_t();
if( NULL == message_queue )exit(WING_BAD_ERROR);
initQueue(message_queue);
//创建完成端口
HANDLE m_hIOCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 );
if(m_hIOCompletionPort == NULL){
RETURN_LONG(WING_ERROR_FAILED);
return;
}
//初始化线程参数
DWORD thread_id= GetCurrentThreadId();
COMPARAMS *accept_params= new COMPARAMS();
if( NULL == accept_params) exit(WING_BAD_ERROR);
accept_params->threadid= thread_id;
accept_params->IOCompletionPort = m_hIOCompletionPort;
//根据cpu数量创建工作线程
SYSTEM_INFO si;
GetSystemInfo(&si);
int m_nProcessors = si.dwNumberOfProcessors;
int m_nThreads = 2 * m_nProcessors;
for (int i = 0; i < m_nThreads; i++)
{
_beginthreadex(NULL, 0, socket_worker, accept_params, 0, NULL);
}
//初始化Socket
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData)!=0){
delete accept_params;
accept_params = NULL;
//memory_sub();
RETURN_LONG(WING_ERROR_FAILED);
return;
}
//WSACleanup( );
//初始化Socket
// 这里需要特别注意,如果要使用重叠I/O的话,这里必须要使用WSASocket来初始化Socket
// 注意里面有个WSA_FLAG_OVERLAPPED参数
SOCKET m_sockListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
if(m_sockListen == INVALID_SOCKET){
WSACleanup();
delete accept_params;
accept_params = NULL;
RETURN_LONG(WING_ERROR_FAILED);
return;
}
struct sockaddr_in ServerAddress;
// 填充地址结构信息
ZeroMemory(&ServerAddress, sizeof(ServerAddress));
ServerAddress.sin_family = AF_INET;
// 这里可以选择绑定任何一个可用的地址,或者是自己指定的一个IP地址
//ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
ServerAddress.sin_addr.s_addr = inet_addr(listen_ip);
ServerAddress.sin_port = htons(port);
// 绑定端口
if (SOCKET_ERROR == bind(m_sockListen, (struct sockaddr *) &ServerAddress, sizeof(ServerAddress))){
_close_socket(m_sockListen);
WSACleanup();
delete accept_params;
accept_params = NULL;
//memory_sub();
RETURN_LONG(WING_ERROR_FAILED);
return;
}
// 开始监听
if( 0 != listen(m_sockListen,SOMAXCONN)){
_close_socket(m_sockListen);
WSACleanup();
delete accept_params;
accept_params = NULL;
RETURN_LONG(WING_ERROR_FAILED);
return;
}
accept_params->Socket = m_sockListen;
//客户端连接进来的处理线程
_beginthreadex(NULL, 0, accept_worker, accept_params, 0, NULL);
int times = 0;
int nSize = 0;
elemType *msg = NULL;//消息
//内存泄漏检测
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
_CrtMemCheckpoint( &s1 );
HANDLE handle = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
unsigned int begin_size = pmc.WorkingSetSize;
zend_printf("size:%d\r\n",pmc.WorkingSetSize);
//int connect_size = 0;
//int new_add_size = 0;
while( true )
{
//判断是否有消息
if(is_emptyQueue(message_queue)){
Sleep(10);
continue;
}
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-1:%d\r\n",pmc.WorkingSetSize-begin_size);
//begin_size = pmc.WorkingSetSize;
//-----获取消息--需要加锁--------------------
EnterCriticalSection(&queue_lock);
outQueue(message_queue,&msg);
/*node_t * _temp_node;
msg= message_queue->head->data;
_temp_node= message_queue->head;
message_queue->head = message_queue->head->next;
if(message_queue->head == NULL)
{
message_queue->tail = NULL;
}
delete(_temp_node);
memory_sub(); */
LeaveCriticalSection(&queue_lock);
if( NULL == msg ){
Sleep(10);
continue;
}
//根据消息ID进行不同的处理
switch(msg->message_id){
//新的连接
case WM_ONCONNECT:
{
//zend_printf("onconnect\r\n");
zval *params = NULL;
zval *retval_ptr = NULL;
MAKE_STD_ZVAL(params);
ZVAL_LONG(params,(long)msg->wparam);//socket资源
MAKE_STD_ZVAL(retval_ptr);
if( SUCCESS != call_user_function(EG(function_table),NULL,onconnect,retval_ptr,1,¶ms TSRMLS_CC) ){
zend_error(E_USER_WARNING,"onconnect call_user_function fail");
}
zval_ptr_dtor(&retval_ptr);
zval_ptr_dtor(¶ms);
//zend_printf("onconnect end\r\n");
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-onconnect:%d\r\n",pmc.WorkingSetSize-msg->size);
//connect_size = pmc.WorkingSetSize;
//new_add_size+=pmc.WorkingSetSize-msg->size;
}
break;
case WM_ONSEND:{
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-onsend:%d\r\n",pmc.WorkingSetSize-msg->size);
}break;
//目前暂时没有用到 先留着
case WM_ACCEPT_ERROR:
{
//zend_printf("accept error\r\n");
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-accepterror:%d\r\n",pmc.WorkingSetSize-msg->size);
}
break;
//收到消息
case WM_ONRECV:
{
//zend_printf("onrecv\r\n");
RECV_MSG *temp = (RECV_MSG*)msg->lparam;
SOCKET client = (SOCKET)msg->wparam;
zval *params[2] = {0};
zval *retval_ptr = NULL;
MAKE_STD_ZVAL(params[0]);
MAKE_STD_ZVAL(params[1]);
MAKE_STD_ZVAL(retval_ptr);
ZVAL_LONG(params[0],(long)client);
ZVAL_STRINGL(params[1],temp->msg,temp->len,1);
//zend_printf("2-onrecv\r\n");
if( SUCCESS != call_user_function(EG(function_table),NULL,onreceive,retval_ptr,2,params TSRMLS_CC) ){
zend_error(E_USER_WARNING,"onreceive call_user_function fail");
}
//zend_printf("30-onrecv\r\n");
zval_ptr_dtor(&retval_ptr);
zval_ptr_dtor(¶ms[0]);
zval_ptr_dtor(¶ms[1]);
//zend_printf("3-onrecv\r\n");
memory_sub_bytes(sizeof(char)*(temp->len));
delete[] temp->msg;
temp->msg = NULL;
memory_sub_bytes(sizeof(RECV_MSG));
delete temp;
temp = NULL;
memory_sub();
memory_sub();
//zend_printf("onrecv end\r\n");
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-onrecv:%d\r\n",pmc.WorkingSetSize-msg->size);
//new_add_size+=pmc.WorkingSetSize-msg->size;
}
break;
//调用 _close_socket 服务端主动关闭socket
case WM_ONCLOSE_EX:{
//zend_printf("close ex\r\n");
_close_socket((SOCKET)msg->wparam);
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-onclose ex:%d\r\n",pmc.WorkingSetSize-msg->size);
}break;
case WM_TEST:
{
zend_printf("test---------------------------------------:%d\r\n",msg->size);
}
break;
//客户端掉线了
case WM_ONCLOSE:
{
//zend_printf("onclose\r\n");
SOCKET client =(SOCKET)msg->wparam;
zval *params = NULL;
zval *retval_ptr = NULL;
MAKE_STD_ZVAL(params);
ZVAL_LONG(params,(long)client);
MAKE_STD_ZVAL(retval_ptr);
if(SUCCESS != call_user_function(EG(function_table),NULL,onclose,retval_ptr,1,¶ms TSRMLS_CC)){
zend_error(E_USER_WARNING,"WM_ONCLOSE call_user_function fail\r\n");
}
zval_ptr_dtor(&retval_ptr);
zval_ptr_dtor(¶ms);
//zend_printf("onclose end\r\n");
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-onclose:%d\r\n",pmc.WorkingSetSize-msg->size);
//new_add_size = 0;
}
break;
//发生错误 目前暂时也还没有用到
case WM_ONERROR:{
//zend_printf("------------------------------------onerror----warning-------------------------------\r\n");
SOCKET client =(SOCKET)msg->wparam;
zval *params = NULL;
zval *retval_ptr = NULL;
MAKE_STD_ZVAL(params);
//ZVAL_STRING(params[1],(char*)msg.lParam,1);
ZVAL_LONG(params,(long)msg->lparam);
MAKE_STD_ZVAL(retval_ptr);
if(SUCCESS != call_user_function(EG(function_table),NULL,onerror,retval_ptr,1,¶ms TSRMLS_CC)){
zend_error(E_USER_WARNING,"onerror call_user_function fail");
}
zval_ptr_dtor(&retval_ptr);
zval_ptr_dtor(¶ms);
//zend_printf("onerror end\r\n");
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-onerror:%d\r\n",pmc.WorkingSetSize-msg->size);
}
break;
//退出服务 暂时没有测试
case WM_ONQUIT:
{
//zend_printf("quit\r\n");
PostQueuedCompletionStatus(m_hIOCompletionPort, 0xFFFFFFFF, 0, NULL);
CloseHandle(m_hIOCompletionPort);
_close_socket(m_sockListen);
WSACleanup();
clearQueue(message_queue);
DeleteCriticalSection(&queue_lock);
//memory_sub_bytes(sizeof(message_queue));
//memory_sub_bytes(sizeof(accept_params));
memory_sub_bytes(sizeof(elemType));
delete accept_params;
delete msg;
delete message_queue;
accept_params = NULL;
msg = NULL;
message_queue = NULL;
//zend_printf("quit end\r\n");
RETURN_LONG(WING_SUCCESS);
return;
}break;
}
memory_sub_bytes(sizeof(elemType));
delete msg;
msg = NULL;
memory_sub();
//显示内存申请 释放次数对比
memory_times_show();
_CrtMemCheckpoint( &s2 );
if ( _CrtMemDifference( &s3, &s1, &s2) )
{
//zend_printf("memory crash\r\n");
_CrtMemDumpStatistics( &s3 );//内存泄露
}
else {
//zend_printf("memory not crash\r\n");
}
//call_cycle
/*zval *retval_ptr = NULL;
MAKE_STD_ZVAL(retval_ptr);
call_user_function(EG(function_table),NULL,call_cycle,retval_ptr,0,NULL TSRMLS_CC);
zval_ptr_dtor(&retval_ptr);*/
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
zend_printf("size-last:%d\r\n",pmc.WorkingSetSize-begin_size);
}
zend_printf("service quit\r\n");
RETURN_LONG(WING_SUCCESS);
}
/***********************************
* @停止服务
***********************************/
ZEND_FUNCTION(wing_service_stop){
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return;
}
memory_add();
memory_add_bytes(sizeof(elemType));
HANDLE handle = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
msg->message_id = WM_ONQUIT;
msg->wparam = 0;
msg->lparam = 0;
msg->size = pmc.WorkingSetSize;
enQueue(message_queue,msg);
RETURN_LONG(WING_SUCCESS);
}
/********************************************
* @ 关闭socket
* @ param socket
********************************************/
ZEND_FUNCTION(wing_close_socket){
zval *socket = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z",&socket) != SUCCESS) {
RETURN_LONG(WING_ERROR_PARAMETER_ERROR);
return;
}
convert_to_long(socket);
//_close_socket((SOCKET)socket);
elemType *msg = new elemType();
if( NULL == msg ){
_throw_error(WING_ERROR_MALLOC);
return;
}
memory_add();
memory_add_bytes(sizeof(elemType));
HANDLE handle = GetCurrentProcess();
PROCESS_MEMORY_COUNTERS pmc;
GetProcessMemoryInfo(handle, &pmc, sizeof(pmc));
msg->message_id = WM_ONCLOSE_EX;
msg->wparam = (unsigned long)Z_LVAL_P(socket);
msg->lparam = 0;
msg->size = pmc.WorkingSetSize;
enQueue(message_queue,msg);
RETURN_LONG(WING_SUCCESS);
return;
}
/*****************************************
* @获取socket信息,ip 协议 端口 等
* @return array
****************************************/
ZEND_FUNCTION(wing_socket_info){
zval *socket = NULL;
MAKE_STD_ZVAL(socket);
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z",&socket) != SUCCESS) {
RETURN_LONG(WING_ERROR_PARAMETER_ERROR);
return;
}
convert_to_long(socket);
SOCKADDR_IN addr_conn;
int nSize = sizeof(addr_conn);
//memset((void *)&addr_conn,0,sizeof(addr_conn));
ZeroMemory(&addr_conn,sizeof(addr_conn));
getpeername((SOCKET)Z_LVAL_P(socket),(SOCKADDR *)&addr_conn,&nSize);
array_init(return_value);
add_assoc_string(return_value,"sin_addr",inet_ntoa(addr_conn.sin_addr),1);
add_assoc_long(return_value,"sin_family",addr_conn.sin_family);
add_assoc_long(return_value,"sin_port",addr_conn.sin_port);
add_assoc_string(return_value,"sin_zero",addr_conn.sin_zero,1);
}
/*****************************************
* @ 发送socket数据
* @ 同步发送接口 没有使用iocp
****************************************/
ZEND_FUNCTION(wing_socket_send_msg)
{
zval *socket;
zval *msg;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz",&socket,&msg) != SUCCESS) {
RETURN_LONG(WING_ERROR_PARAMETER_ERROR);
return;
}
convert_to_long(socket);
//此处没有使用完成端口 完成端口发送后 如果直接调用 socketclose
//关闭socket 有坑,处理不好会有内存泄漏
if( SOCKET_ERROR == send((SOCKET)Z_LVAL_P(socket),Z_STRVAL_P(msg),Z_STRLEN_P(msg),0)){
RETURN_LONG(WING_ERROR_FAILED);
return;
}
RETURN_LONG(WING_SUCCESS);
}
/***************************************************
* @ 使用iocp异步发送消息
***************************************************/
ZEND_FUNCTION(wing_socket_send_msg_ex){
zval *socket = NULL;
zval *msg = NULL;
int close_after_send = 0;//发送完关闭socket 默认为false 否 待定 还没开发
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l",&socket,&msg,&close_after_send) != SUCCESS) {
RETURN_LONG(WING_ERROR_PARAMETER_ERROR);
return;
}
convert_to_long(socket);
SOCKET sClient= (SOCKET)Z_LVAL_P(socket);
char *pData= Z_STRVAL_P(msg);
ulong Length= Z_STRLEN_P(msg);
unsigned long Flag= 0;
DWORD SendByte= 0;
if ( sClient == INVALID_SOCKET || pData == NULL || Length == 0 ){
RETURN_LONG(WING_ERROR_FAILED);
return;
}
PER_IO_OPERATION_DATA *PerIoData = new PER_IO_OPERATION_DATA();
memory_add();
memory_add_bytes(sizeof(PER_IO_OPERATION_DATA));
ZeroMemory(&(PerIoData->OVerlapped),sizeof(OVERLAPPED));
PerIoData->DATABuf.buf= pData;
PerIoData->DATABuf.len= Length;
PerIoData->type= OPE_SEND;
int bRet = WSASend(sClient,&(PerIoData->DATABuf),1,&SendByte,Flag,&(PerIoData->OVerlapped),NULL);
if( bRet != 0 && WSAGetLastError() != WSA_IO_PENDING ){
memory_sub_bytes(sizeof(PER_IO_OPERATION_DATA));
delete PerIoData;
PerIoData = NULL;
memory_sub();
RETURN_LONG(WING_ERROR_FAILED);
return;
}
RETURN_LONG(WING_SUCCESS);
}