//一个简单的使用例子
//连接远程服务器成功 或 接收到一个远程连接时,本函数将会被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;
}