iocp端口断开_iocp-完成端口内存泄露问题,求高手解答?

关键源码

/*****************************************************************************************

* @ 关闭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,&params TSRMLS_CC) ){

zend_error(E_USER_WARNING,"onconnect call_user_function fail");

}

zval_ptr_dtor(&retval_ptr);

zval_ptr_dtor(&params);

//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(&params[0]);

zval_ptr_dtor(&params[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,&params TSRMLS_CC)){

zend_error(E_USER_WARNING,"WM_ONCLOSE call_user_function fail\r\n");

}

zval_ptr_dtor(&retval_ptr);

zval_ptr_dtor(&params);

//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,&params TSRMLS_CC)){

zend_error(E_USER_WARNING,"onerror call_user_function fail");

}

zval_ptr_dtor(&retval_ptr);

zval_ptr_dtor(&params);

//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);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值