int skynet_multicast_castgroup(struct skynet_context * from, struct skynet_multicast_group * group, struct skynet_multicast_message *msg) { combine_queue(from, group); int release = 0; if (group->number > 0) { uint32_t source = skynet_context_handle(from); skynet_multicast_copy(msg, group->number); int i; for (i=0;i<group->number;i++) { uint32_t p = group->data[i]; struct skynet_context * ctx = skynet_handle_grab(p); if (ctx) { skynet_context_send(ctx, msg, 0 , source, PTYPE_MULTICAST , 0); skynet_context_release(ctx); } else { skynet_multicast_leavegroup(group, p); ++release; } } } skynet_multicast_copy(msg, -release); return group->number - release; }
int skynet_multicast_castgroup(struct skynet_context * from, struct skynet_multicast_group * group, struct skynet_multicast_message *msg) { combine_queue(from, group); if (group->number == 0) { skynet_multicast_dispatch(msg, NULL, NULL); return 0; } uint32_t source = skynet_context_handle(from); skynet_multicast_copy(msg, group->number); int i; int release = 0; for (i=0;i<group->number;i++) { struct pair * p = &group->data[i]; skynet_context_send(p->ctx, msg, 0 , source, PTYPE_MULTICAST , 0); int ref = skynet_context_ref(p->ctx); if (ref == 1) { skynet_context_release(p->ctx); struct skynet_context * ctx = skynet_handle_grab(p->handle); if (ctx == NULL) { p->ctx = NULL; skynet_multicast_leavegroup(group, p->handle); ++release; } } } return group->number - release; }
// 多播的主要处理函数 static int _maincb(struct skynet_context * context, void * ud, int type, int session, uint32_t source, const void * msg, size_t sz) { struct skynet_multicast_group *g = ud; // PTYPE_SYSTEM 协议控制命令 if (type == PTYPE_SYSTEM) { char cmd = '\0'; uint32_t handle = 0; sscanf(msg,"%c %x",&cmd,&handle); // 格式化参数 if (handle == 0) { skynet_error(context, "Invalid handle %s",msg); return 0; } // 简单的命令协议 switch (cmd) { case 'E': skynet_multicast_entergroup(g, handle); break; case 'L': skynet_multicast_leavegroup(g, handle); break; case 'C': skynet_command(context, "EXIT", NULL); break; default: skynet_error(context, "Invalid command %s",msg); break; } return 0; } // 发送消息出去 else { sz |= type << HANDLE_REMOTE_SHIFT; struct skynet_multicast_message * mc = skynet_multicast_create(msg, sz, source); skynet_multicast_castgroup(context, g, mc); return 1; } }