IOCP简易实现(客户端与客户端之间可以聊天)

client.cpp

#include "stdAfx.h"
#include <iostream>
#include <cstdio>  
#include <string>  
#include <cstring>  
#include <winsock2.h>  
#include <Windows.h>  

using namespace std;  

#pragma comment(lib, "Ws2_32.lib")      // Socket编程需用的动态链接库  

SOCKET sockClient;      // 连接成功后的套接字  
HANDLE bufferMutex;     // 令其能互斥成功正常通信的信号量句柄    

int main()  
{  
 // 加载socket动态链接库(dll)  
 WORD wVersionRequested;  
 WSADATA wsaData;    // 这结构是用于接收Wjndows Socket的结构信息的  
 wVersionRequested = MAKEWORD( 2, 2 );   // 请求2.2版本的WinSock库  
 int err = WSAStartup( wVersionRequested, &wsaData );  
 if ( err != 0 ) {   // 返回值为零的时候是表示成功申请WSAStartup  
  return -1;  
 }  
 if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { // 检查版本号是否正确  
  WSACleanup( );  
  return -1;  
 }  

 // 创建socket操作,建立流式套接字,返回套接字号sockClient  
 sockClient = socket(AF_INET, SOCK_STREAM, 0);  
 if(sockClient == INVALID_SOCKET) {  
  printf("Error at socket():%ld\n", WSAGetLastError());  
  WSACleanup();  
  return -1;  
 }  

 // 将套接字sockClient与远程主机相连  
 // int connect( SOCKET s,  const struct sockaddr* name,  int namelen);  
 // 第一个参数:需要进行连接操作的套接字  
 // 第二个参数:设定所需要连接的地址信息  
 // 第三个参数:地址的长度  
 SOCKADDR_IN addrSrv;  
 addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.19");      // 本地回路地址是127.0.0.1;  
 addrSrv.sin_family = AF_INET;  
 int a;
 cout<<"请输入端口:";
 cin>>a;
 addrSrv.sin_port = htons(a);  
 while(SOCKET_ERROR == connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR))){  
  // 如果还没连接上服务器则要求重连  
  cout << "服务器连接失败,是否重新连接?(Y/N):";  
  char choice;  
  while(cin >> choice && (!((choice != 'Y' && choice == 'N') || (choice == 'Y' && choice != 'N')))){  
   cout << "输入错误,请重新输入:";  
   cin.sync();  
   cin.clear();  
  }  
  if (choice == 'Y'){  
   continue;  
  }  
  else{  
   cout << "退出系统中...";  
   system("pause");  
   return 0;  
  }  
 }  
 cin.sync();  
 cout << "本客户端已准备就绪,用户可直接输入文字向服务器反馈信息。\n";  

 send(sockClient, "\nHey~Boy!!\n", 200, 0);  

 bufferMutex = CreateSemaphore(NULL, 1, 1, NULL);  

 DWORD WINAPI SendMessageThread(LPVOID IpParameter);  
 DWORD WINAPI ReceiveMessageThread(LPVOID IpParameter);  

 HANDLE sendThread = CreateThread(NULL, 0, SendMessageThread, NULL, 0, NULL);    
 HANDLE receiveThread = CreateThread(NULL, 0, ReceiveMessageThread, NULL, 0, NULL);    


 WaitForSingleObject(sendThread, INFINITE);  // 等待线程结束  
 closesocket(sockClient);  
 CloseHandle(sendThread);  
 CloseHandle(receiveThread);  
 CloseHandle(bufferMutex);  
 WSACleanup();   // 终止对套接字库的使用  

 printf("End linking...\n");  
 printf("\n");  
 system("pause");  
 return 0;  
}  


DWORD WINAPI SendMessageThread(LPVOID IpParameter)  
{  
 while(1){  
  char chatting[204];
  getchar();
  WaitForSingleObject(bufferMutex, INFINITE);     // P(资源未被占用)  
  cout<<"请输入内容:";
  ReleaseSemaphore(bufferMutex, 1, NULL);
  gets(chatting+4);
  WaitForSingleObject(bufferMutex, INFINITE);
  cout<<"请输入ID:";
  ReleaseSemaphore(bufferMutex, 1, NULL);
  int i_ID;
  cin>>i_ID;
  memcpy(chatting,&i_ID,4);
  WaitForSingleObject(bufferMutex, INFINITE);  
  send(sockClient, chatting, 200, 0); // 发送信息  
  ReleaseSemaphore(bufferMutex, 1, NULL);     // V(资源占用完毕)  
 }  
 return 0;  
}  


DWORD WINAPI ReceiveMessageThread(LPVOID IpParameter)  
{ char recvBuf[2048];
 char flags;
 int number;
 while(recv(sockClient, recvBuf, 2048, 0)>0){  
  WaitForSingleObject(bufferMutex, INFINITE);     // P(资源未被占用)    
  cout<<endl;
  for (int i=0;i<(50);i++)
  {
   cout<<" ";
  }
  flags = recvBuf[0];
  if ('f'==flags)
  {
   cout<<"服务器:"<<recvBuf+1<<endl;
  }
  else
  {
   number = *(int*)recvBuf;
   cout<<number<<"号客户端:"<<recvBuf+4<<endl;
  }
  ReleaseSemaphore(bufferMutex, 1, NULL);     // V(资源占用完毕)  
 }  
 return 0;  
}  

IOCP.cpp

#include "stdafx.h"
#include <iostream>
#include "List.h"
#define  RECV 1
#define  SEND 2
#define  ACCEPT 0
#define  DISCONNECT 3
#define  FREE 4
const int DefaultPort = 8000;
const int ALLUSERS = 1000;
using namespace std;

List<OVERLAPEDEx*> per_IOpool;
List<OVERLAPEDEx*> per_IOusing;
List<PERSOCKET*> per_socketpool;
List<PERSOCKET*> per_socketusing;

PERSOCKET* Userssocket;
int onlineusers = 0,
 acceptedflags = 1,
 acceptwillflags = 1,
 acceptcheck = 1;

GUID GuidAcceptEx =  WSAID_ACCEPTEX;
LPFN_ACCEPTEX CSY_AcceptEx = NULL;
GUID GuiddisconnectEx = WSAID_DISCONNECTEX;
LPFN_DISCONNECTEX CSY_Disconnect = NULL;
HANDLE mutex = CreateMutex(NULL,FALSE,NULL);

#pragma comment(lib, "Ws2_32.lib")
#pragma comment(lib, "Kernel32.lib")
#pragma comment(lib,"Mswsock.lib")

void AcceptIO(OVERLAPEDEx*);
void RecvIO(OVERLAPEDEx*);
void SendIO(OVERLAPEDEx*);
void DisconnectIO(OVERLAPEDEx*);
unsigned int __stdcall srvsend(void *complt)
{
 char chatting[200];
 int a;
 while (1)
 {
  getchar();
  if ((per_socketusing.size)>0)
  {
   if (onlineusers>0)
   {
    WaitForSingleObject(mutex,INFINITE);
    cout<<endl<<"请输入内容:";
    ReleaseMutex(mutex);
    gets(chatting+1);
   }
   WaitForSingleObject(mutex,INFINITE);
   chatting[0] = 'f';
   node<PERSOCKET*>* temp = temp = per_socketusing.head;
   for (int i=0;i<per_socketusing.size;i++)
   {
    if (send(Userssocket[temp->data->UserID].socket,chatting,200,0)<0)
    {
     cout<<"No."<<a<<" can't connect server"<<endl;
    }
    else
    {
     cout<<"回执已发送。"<<endl;
    }
    temp = temp->next;
   }
   ReleaseMutex(mutex);
  }
  else
  {
   WaitForSingleObject(mutex,INFINITE);
   cout<<"There is no client link~"<<endl;
   ReleaseMutex(mutex);
  }
 }
}


unsigned int __stdcall srvrecv(void *complt)
{
 HANDLE completion = (HANDLE)complt;
 DWORD transbytes;
 DWORD recvbytes;
 DWORD Recvbytes;
 DWORD flags = 0;
 DWORD Flags = 0;
 LPOVERLAPPED theoverlaped = NULL;
 OVERLAPEDEx *peroverlapedex = NULL;
 PERSOCKET *thesocket = NULL;
 int gqc = 1;
 while (1)
 {
  gqc = GetQueuedCompletionStatus(completion,
   &transbytes,
   (PULONG_PTR)&thesocket,
   (LPOVERLAPPED*)&theoverlaped,
   INFINITE);
  peroverlapedex = (OVERLAPEDEx*)theoverlaped;
  if (gqc==0&&transbytes==0)
  {
   DWORD a = GetLastError();
   WaitForSingleObject(mutex,INFINITE);
   onlineusers--;
   cout<<"No."<<peroverlapedex->UserID<<"client exit,error="<<a<<endl;
   per_socketpool.add(&Userssocket[peroverlapedex->UserID]);
   per_socketusing.remove(&Userssocket[peroverlapedex->UserID]);
   cout<<"回收Socket..."<<endl;
   cout<<"剩余Socket:"<<per_socketpool.size;
   cout<<" 正在使用Socket:"<<per_socketusing.size<<endl;
   peroverlapedex->IOType = FREE;
   cout<<"投递Disconnect..."<<endl;
   cout<<"剩余IO:"<<per_IOpool.size;
   cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
   CSY_Disconnect(thesocket->socket,
    &peroverlapedex->overlaped,
    TF_REUSE_SOCKET,
    0);

   node<PERSOCKET*>* temp = temp = per_socketusing.head;
   for (int i=0;i<per_socketusing.size;i++)
   {
    ZeroMemory(&(per_IOpool.head->data->overlaped), sizeof(OVERLAPPED));
    per_IOpool.head->data->databuff.buf = per_IOpool.head->data->buffer;
    sprintf(per_IOpool.head->data->buffer,"f%d号客户端下线了,当前有%d人在线",thesocket->UserID,per_socketusing.size);
    per_IOpool.head->data->databuff.len = 32;
    per_IOpool.head->data->IOType = SEND;
    per_IOpool.head->data->UserID = per_socketusing.tail->data->UserID;
    per_IOpool.head->data->socket = (HANDLE)per_socketusing.tail->data->socket;
    WSASend(temp->data->socket,
     &per_IOpool.head->data->databuff,
     1,
     &Recvbytes,
     flags,
     &per_IOpool.head->data->overlaped,
     0);
    per_IOusing.add(per_IOpool.head->data);
    per_IOpool.removehead();
    cout<<"投递WSASend..."<<endl;
    cout<<"剩余IO:"<<per_IOpool.size;
    cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
    temp = temp->next;
   }
   ReleaseMutex(mutex);
   continue;
  }
  if (peroverlapedex->IOType==ACCEPT)
  {
   WaitForSingleObject(mutex,INFINITE);
   per_socketusing.add(per_socketpool.head->data);
   per_socketpool.removehead();  
   cout<<"获取Socket..."<<endl;
   cout<<"剩余Socket:"<<per_socketpool.size;
   cout<<" 正在使用Socket:"<<per_socketusing.size<<endl;
   onlineusers++;
   acceptedflags = 0;

   CreateIoCompletionPort((HANDLE)per_socketusing.tail->data->socket,
    completion,
    (DWORD)&per_socketusing.tail->data->socket,
    0);
   char ip[4] = {0};
   for (int i=2026,n=0;i<2030;++i,++n)
   {
    ip[n] = peroverlapedex->buffer[i];
   }
   int IP[4];
   for (int i=0;i<4;++i)
   {
    IP[i] = ((int)ip[i]+256)%256;
   }

   cout<<"IP:"<<IP[0]<<"."<<IP[1]<<"."<<IP[2]<<"."<<IP[3]<<":"<<peroverlapedex->databuff.buf<<endl;

   ZeroMemory(&(per_IOpool.head->data->overlaped), sizeof(OVERLAPPED));
   per_IOpool.head->data->databuff.buf = per_IOpool.head->data->buffer;
   sprintf(per_IOpool.head->data->buffer,"f登录成功,当前有%d人在线",per_socketusing.size);
   per_IOpool.head->data->databuff.len = 25;
   per_IOpool.head->data->IOType = SEND;
   per_IOpool.head->data->UserID = per_socketusing.tail->data->UserID;
   per_IOpool.head->data->socket = (HANDLE)per_socketusing.tail->data->socket;
   WSASend(per_socketusing.tail->data->socket,
    &per_IOpool.head->data->databuff,
    1,
    &Recvbytes,
    flags,
    &per_IOpool.head->data->overlaped,
    0);
   per_IOusing.add(per_IOpool.head->data);
   per_IOpool.removehead();
   cout<<"投递WSASend..."<<endl;
   cout<<"剩余IO:"<<per_IOpool.size;
   cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
   node<PERSOCKET*>* temp = temp = per_socketusing.head;
   for (int i=0;i<per_socketusing.size-1;i++)
   {
    ZeroMemory(&(per_IOpool.head->data->overlaped), sizeof(OVERLAPPED));
    per_IOpool.head->data->databuff.buf = per_IOpool.head->data->buffer;
    sprintf(per_IOpool.head->data->buffer,"f%d号客户端上线了,当前有%d人在线",per_socketusing.tail->data->UserID,per_socketusing.size);
    per_IOpool.head->data->databuff.len = 32;
    per_IOpool.head->data->IOType = SEND;
    per_IOpool.head->data->UserID = per_socketusing.tail->data->UserID;
    per_IOpool.head->data->socket = (HANDLE)per_socketusing.tail->data->socket;
    WSASend(temp->data->socket,
     &per_IOpool.head->data->databuff,
     1,
     &Recvbytes,
     flags,
     &per_IOpool.head->data->overlaped,
     0);
    per_IOusing.add(per_IOpool.head->data);
    per_IOpool.removehead();
    cout<<"投递WSASend..."<<endl;
    cout<<"剩余IO:"<<per_IOpool.size;
    cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
    temp = temp->next;
   }

   ZeroMemory(&(peroverlapedex->overlaped), sizeof(OVERLAPPED));
   peroverlapedex->databuff.buf = peroverlapedex->buffer;
   peroverlapedex->databuff.len = 2048;
   peroverlapedex->IOType = RECV;
   peroverlapedex->UserID = per_socketusing.tail->data->UserID;
   peroverlapedex->socket = (HANDLE)per_socketusing.tail->data->socket;
   WSARecv(per_socketusing.tail->data->socket,
    &peroverlapedex->databuff,
    1,
    &recvbytes,
    &Flags,
    &peroverlapedex->overlaped,
    0);
   ReleaseMutex(mutex);
  }
  else
  {
   if (peroverlapedex->IOType==RECV)
   {
    WaitForSingleObject(mutex,INFINITE);
    cout<<"客户端"<<peroverlapedex->UserID<<"号:"<<peroverlapedex->databuff.buf+4<<endl;

    ZeroMemory(&(per_IOpool.head->data->overlaped), sizeof(OVERLAPPED));
    per_IOpool.head->data->databuff.buf = per_IOpool.head->data->buffer;
    strcpy(per_IOpool.head->data->databuff.buf+4,peroverlapedex->databuff.buf+4);
    memcpy(per_IOpool.head->data->databuff.buf,&peroverlapedex->UserID,4);
    per_IOpool.head->data->databuff.len = strlen(peroverlapedex->databuff.buf+4)+5;
    per_IOpool.head->data->IOType = SEND;
    per_IOpool.head->data->UserID = *(int*)(peroverlapedex->buffer);
    per_IOpool.head->data->socket = (HANDLE)Userssocket[*(int*)peroverlapedex->buffer].socket;
    WSASend(Userssocket[*(int*)peroverlapedex->buffer].socket,
     &per_IOpool.head->data->databuff,
     1,
     &Recvbytes,
     flags,
     &per_IOpool.head->data->overlaped,
     0);
    per_IOusing.add(per_IOpool.head->data);
    per_IOpool.removehead();
    cout<<"投递WSASend..."<<endl;
    cout<<"剩余IO:"<<per_IOpool.size;
    cout<<" 正在使用IO:"<<per_IOusing.size<<endl;

    ZeroMemory(peroverlapedex, sizeof(OVERLAPPED));
    peroverlapedex->databuff.buf = peroverlapedex->buffer;
    peroverlapedex->databuff.len = 2048;
    peroverlapedex->IOType = RECV;
    WSARecv(Userssocket[peroverlapedex->UserID].socket,
     &peroverlapedex->databuff,
     1,
     &recvbytes,
     &flags,
     &peroverlapedex->overlaped,
     0);
    cout<<"投递WSARecv..."<<endl;
    cout<<"剩余IO:"<<per_IOpool.size;
    cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
    ReleaseMutex(mutex);
   }
   else
   {
    if (peroverlapedex->IOType==SEND)
    {
     WaitForSingleObject(mutex,INFINITE);
     per_IOpool.add(peroverlapedex);
     per_IOusing.remove(peroverlapedex);
     cout<<"回收WSASend..."<<endl;
     cout<<"剩余IO:"<<per_IOpool.size;
     cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
     ReleaseMutex(mutex);
    }
    else
    {
     if (peroverlapedex->IOType==FREE)
     {
      WaitForSingleObject(mutex,INFINITE);
      per_IOpool.add(peroverlapedex);
      per_IOusing.remove(peroverlapedex);
      cout<<"回收WSARecv..."<<endl;
      cout<<"剩余IO:"<<per_IOpool.size;
      cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
      ReleaseMutex(mutex);
     }
     else
     {
      if (peroverlapedex->IOType==DISCONNECT)
      {
       WaitForSingleObject(mutex,INFINITE);
       per_IOpool.add(peroverlapedex);
       per_IOusing.remove(peroverlapedex);
       cout<<"回收Disconnect..."<<endl;
       cout<<"剩余IO:"<<per_IOpool.size;
       cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
       ReleaseMutex(mutex);
      }
     }
    }
   }
  }
 }
 return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
 HANDLE servesend;
 WORD winsock =  MAKEWORD(2,2);
 WSADATA wsaData;
 DWORD err = WSAStartup(winsock,&wsaData);
 if (err!=0)
 {
  cerr<<"加载socket动态链接库失败"<<endl;
  system("pause");
 }
 if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
 {
  cerr<<"申请windows socket vision 2.2 错误"<<endl;
  system("pause");
 }
 HANDLE completionPort = CreateIoCompletionPort( (HANDLE)-1, NULL, 0, 0);  
 if (NULL == completionPort)
 {
  cerr << "CreateIoCompletionPort failed. Error:" << GetLastError() << endl;  
  system("pause");  
  return -1;  
 }  
 SYSTEM_INFO mySysInfo;  
 GetSystemInfo(&mySysInfo);  
 for(DWORD i = 0; i < (mySysInfo.dwNumberOfProcessors * 2); ++i){  
  HANDLE ThreadHandle = (HANDLE)_beginthreadex(NULL,0,srvrecv, completionPort, 0, NULL);
  if(NULL == ThreadHandle){  
   cerr << "Create Thread Handle failed. Error:" << GetLastError() << endl;  
   system("pause");  
   return -1;  
  }  
  CloseHandle(ThreadHandle);  
 }
 PERSOCKET* socket_a = new PERSOCKET;
 socket_a->socket = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
 SOCKADDR_IN serveaddr;
 serveaddr.sin_addr.s_addr = htonl(INADDR_ANY);
 serveaddr.sin_family = AF_INET;
 serveaddr.sin_port = htons(DefaultPort);
 int ibind = bind(socket_a->socket,(SOCKADDR*)&serveaddr,sizeof(SOCKADDR));
 if (ibind==-1)
 {
  cerr<<"socket bind error"<<GetLastError()<<endl;
 }

 CreateIoCompletionPort((HANDLE)socket_a->socket,
  completionPort,
  (ULONG_PTR)socket_a,
  0);
 int listento = listen(socket_a->socket,10);
 if (listento==-1)
 {
  cerr<<"listen error"<<GetLastError()<<endl;
  system("pause");
 }

 Userssocket = new PERSOCKET [ALLUSERS];
 for (int i=0;i<ALLUSERS;++i) //socket池
 {
  SOCKET socket_s = socket(AF_INET,SOCK_STREAM,0);
  Userssocket[i].UserID = i;
  Userssocket[i].socket = socket_s;
  per_socketpool.add(&Userssocket[i]);
 }
 OVERLAPEDEx* AllIO[ALLUSERS*3]; //IO池
 for (int i=0;i<ALLUSERS*3;++i)
 {
  AllIO[i] = new OVERLAPEDEx;
  AllIO[i]->IOType = FREE;
  per_IOpool.add(AllIO[i]);
 }
 servesend = (HANDLE)_beginthreadex(NULL,0,srvsend,&per_socketusing,0,NULL);
 DWORD dwBytes;
 WSAIoctl(socket_a->socket,
  SIO_GET_EXTENSION_FUNCTION_POINTER,
  &GuiddisconnectEx,
  sizeof(GuiddisconnectEx),
  &CSY_Disconnect,
  sizeof(LPFN_DISCONNECTEX),
  &dwBytes,
  NULL,
  NULL);
 WSAIoctl(socket_a->socket,
  SIO_GET_EXTENSION_FUNCTION_POINTER, //操作指针
  &GuidAcceptEx, //输入缓冲区地址
  sizeof(GuidAcceptEx),
  &CSY_AcceptEx, //输出缓冲区地址
  sizeof(LPFN_ACCEPTEX),
  &dwBytes, //输出字节的地址
  NULL,
  NULL);
 WaitForSingleObject(mutex,INFINITE);
 cout<<"Ready~~GO!!"<<endl;
 ReleaseMutex(mutex);
 while (1)
 {
  while (acceptwillflags&&(onlineusers<(ALLUSERS)))
  {
   WaitForSingleObject(mutex,INFINITE);
   per_IOusing.add(per_IOpool.head->data);
   per_IOpool.removehead();
   cout<<"投递AcceptEx..."<<endl;
   cout<<"剩余IO:"<<per_IOpool.size;
   cout<<" 正在使用IO:"<<per_IOusing.size<<endl;
   ReleaseMutex(mutex);
    memset(per_IOusing.tail->data,0,size_t(sizeof(OVERLAPEDEx)));
    per_IOusing.tail->data->databuff.len = 2048;
    per_IOusing.tail->data->databuff.buf = per_IOusing.tail->data->buffer;
    per_IOusing.tail->data->IOType = ACCEPT;
    per_IOusing.tail->data->UserID = per_socketpool.head->data->UserID;
    per_IOusing.tail->data->socket = (HANDLE)&per_socketpool.head->data->socket;
    DWORD i_dwBytes;
    int ca = sizeof(IN_ADDR);
    int cf = sizeof(SOCKADDR_IN);
    WaitForSingleObject(mutex,INFINITE);
    int i_acc = AcceptEx(socket_a->socket,
     per_socketpool.head->data->socket,
     per_IOusing.tail->data->databuff.buf,
     per_IOusing.tail->data->databuff.len-(sizeof(SOCKADDR_IN)+16)*2,
     sizeof(SOCKADDR_IN)+16,
     sizeof(SOCKADDR_IN)+16,
     &i_dwBytes,
     &(per_IOusing.tail->data->overlaped));
    if (i_acc==0&&GetLastError()!=997)
    {
     cout<<"accept socket error"<<GetLastError()<<endl;
     system("pause");
    }
    acceptedflags = 1;
    acceptcheck = 1;
    acceptwillflags = 0;
    ReleaseMutex(mutex);
  }
  while(acceptcheck)
  {
   if (acceptedflags==0)
   {
    acceptwillflags = 1;
    acceptcheck = 0;
   }
  }
 }
 return 0;
}


List.h

#include <WinSock2.h>  
#include "mswsock.h"
#include <Windows.h>  
#include <process.h>
template<class T>
struct node
{
 node<T>* next;
 node<T>* prev;
 T data;
};
template<class T>
class List
{
public:
 node<T>* head;
 node<T>* tail;
 int size;
 List()
 {
  head = NULL;
  tail = NULL;
  size = 0;
 }
 node<T>* add(T data)
 {
  node<T>* temp = new node<T>;
  if (size)
  {
   temp->data = data;
   temp->next = NULL;
   temp->prev = tail;
   tail->next = temp;
   tail = temp;
  }
  else
  {
   temp->data = data;
   head = temp;
   tail = temp;
   temp->next = NULL;
   temp->prev = NULL;
  }
  size++;
  return temp;
 }
 node<T>* find(T data)
 {
  node<T>* temp = NULL;
  for (temp=this->head;temp!=NULL&&temp->data!=data;temp=temp->next)
  {
  }
  return temp;
 }
 void removehead()
 {
  if (size>1)
  {
   node<T>* temp = head;
   head = head->next;
   head->prev = NULL;
   delete temp;
   temp = NULL;
  }
  else
  {
   delete head;
   head = NULL;
   tail = NULL;
  }
  size--;
 }
 void removetail()
 {
  if (size>1)
  {
   node<T>* temp = tail;
   tail = tail->prev;
   tail->next = NULL;
   delete temp;
   temp = NULL;
  }
  else
  {
   delete tail;
   head = NULL;
   tail = NULL;
  }
  size--;
 }
 void removeall()
 {
  if (size>1)
  {
   node<T>* temp;
   for (temp=head->next;temp!=NULL;temp=temp->next)
   {
    delete head;
    head = temp;
   }
   delete head;
   head = NULL;
   tail = NULL;
   size = 0;
  }
  else
  {
   delete head;
   head = NULL;
   tail = NULL;
   size = 0;
  }
 }
 node<T>* remove(T data)
 {
  node<T>* temp = this->find(data);
  if (temp!=NULL)
  {
   if (temp->next==NULL)
   {
    this->removetail();
   }
   else
   {
    if (temp->prev==NULL)
    {
     this->removehead();
    }
    else
    {
     temp->prev->next = temp->next;
     temp->next->prev = temp->prev;
     delete temp;
     temp = NULL;
     size--;
    }
   }
  }
  return temp;
 }
};
struct OVERLAPEDEx
{
 OVERLAPPED overlaped;
 WSABUF databuff;
 char buffer[2048];
 HANDLE socket;
 int IOType;
 int UserID;
};
struct PERSOCKET
{
 SOCKET socket;
 int UserID;
 SOCKADDR_IN clientddr;
};

//一个简单的使用例子 //连接远程服务器成功 或 接收到一个远程连接时,本函数将会被ioc.dll回调.在本函数中,应该向客户端列表中添加节点,记得加锁 // //2.s :套接字句柄,标志着一个新的连接 //3.u_addr:对端的IP地址,网络字节序 //4.u_port:对端的端口号,网络字节序 //5.flag :如果是本地连接上了一个远程服务器,flag值为0,或者,是接收到一个远程客户端的连接,这时,flag值为1 //6.返回值:返回一个自定义的值,这个值将在其他回调函数中作为参数传递(注意:就如套接字句柄一样,这个值也最 //好能标志一个连接,比如,客户端列表的某个节点的指针,假设用STL中的MAP来维护客户端列表,那么用KEY作为返回值也不错。) long _stdcall ioc_call_connect(HIOC hIoc,HINT s,long u_addr,long u_port,long flag) { long res=0; printf("socket(%d) connected\n",s); return res; } //断开与远程服务器的连接 或 远程客户端断开,本函数将会被ioc.dll回调.在本函数中,你可以删除客户节点,记得加锁 //s :套接字句柄,标志着哪个连接断开了(在本回调函数返回之前,套接字句柄s不可能被重新利用,所以,用s作为关键字构建客户端列表也是没有问题的) //res:ioc_call_connect回调函数返回的那个值,如果它是客户端列表的某个节点的话,那么可以删除了。 void _stdcall ioc_call_disconnect(HIOC hIoc,HINT s,long res,long flag) { printf("socket(%d) disconnected\n",s); } //当ioc内部一收到数据就会回调本函数,所谓数据有可能是多个数据包,也有可能是一个不完整的数据包 //hIoc,s,flag都不再多做解释 //res :ioc_call_oprate_dat和ioc_call_disconnect一定是被线性回调的,不可能存在同时执行的情况,所以,res如果指向某个节点的话,在本函数中可以不加锁地尽情访问,在本函数返回之前,res不会被释放掉 //hArg:数据调度句柄 //data:数据 //len :数据大小 //返回值:返回剩余未处理完的字节数 long _stdcall ioc_call_oprate_dat(HIOC hIoc,HARG hArg,HINT s,long res,long flag,char *data,long len) { //假如数据包格式是这样: //struct DATAPACK //{ // long size; long cmd; ...... //}; //如果是这样的话,那么典型的处理方法如下: char *p=data; long size_res=len;//收到数据的总字节数 long size_per;//其中某一个数据包的字节数 while(1) { if(size_res<4) return size_res;// size_per=*(long*)(p+0x00);//取数据包的实际长度 if(size_per<0 || size_per>某个最大值) { ::iocCommon_CloseSocket(hIoc,s); return 0; } if(size_res<size_per) return size_res;//剩余数据不够一个完整的数据包,返回 //得到一个完整的数据包,可以就地处理,但如果处理这个数据包将会很耗时,那么为了不阻塞工作线程, //只好将其调度给数据处理线程,这里其实可以定义一个结构,除了将数据包调度出去,还可以附带一些其他信息 if(数据包处理起来比较简单) { //处理 } else//调度给数据处理线程 { char *msg=(char*)::malloc(len); ::memcpy(msg,p,size_per); ::iocCommon_DispatchMessage(hIoc,hArg,msg);//hArg就只有这么一个作用 } p+=size_per; size_res-=size_per; } } //阻塞数据处理线程回调函数 void _stdcall ioc_call_oprate_msg(HIOC hIoc,void *msg) { //处理数据包 ::free(msg);//根据谁分配谁释放的原则,释放msg } int main() { ::iocCommon_Startup(); long addr_con=(long)ioc_call_connect; long addr_dis=(long)ioc_call_disconnect; long addr_dat=(long)ioc_call_oprate_dat; long addr_msg=(long)ioc_call_oprate_msg;//这个参数是可选的,可以不要专门的阻塞数据处理线程 HIOC hIoc=::iocCommon_Create(3072,128,addr_con,0,addr_dis,0,addr_dat,0,addr_msg,0);//创建IOC ::iocCommon_SetOprateThread(hIoc);//增加一个工作线程 ::iocCommon_SetOprateThread(hIoc);//增加一个工作线程 //启动服务器,内部循环调用阻塞的accept函数,ioc不考虑客户端连接服务器有多困难,而只考虑如何高效地进行数据传输 //可以再创建几个线程,多调用几个iocServer_Start,各个iocServer_Start绑定不同端口也可以 ::iocServer_Start(hIoc,NULL,6800); ::iocCommon_Cleanup(); return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值