static int cpReactor_client_receive(int fd) { int event_size = sizeof (cpTcpEvent), n, ret = -1; char data[event_size]; //非ET模式会持续通知 n = cpNetRead(fd, data, event_size); if (n > 0) { cpTcpEvent *event = (cpTcpEvent*) data; switch (event->type) { case CP_TCPEVENT_ADD: ret = kill(CPGS->manager_pid, SIGRTMIN); if (ret < 0) {//TODO cpLog("send sig error. Error: %s [%d]", strerror(errno), errno); } break; case CP_TCPEVENT_GETFD: { cpMasterInfo info; info.server_fd = fd; CPGS->conlist[fd].fpm_pid = event->data; ret = cpWrite(fd, &info, sizeof (info)); break; } default: cpLog("wrong type"); break; } return ret; } else if (n == 0) { close_fd: return cpReactor_client_close(fd); } else {//需要检测errno来区分是EAGAIN还是ECONNRESET if (errno == EAGAIN) { return SUCCESS; } else if (errno == ECONNRESET) { goto close_fd; } else { cpLog("Read from socket[%d] fail. Error: %s [%d]", fd, strerror(errno), errno); return SUCCESS; } } return SUCCESS; }
CPINLINE static int MasterSend2Client(int fd, int worker_id, int CPid) { CPGS->workers[worker_id].fd = fd; cpMasterInfo info; int sizeinfo = sizeof (info); info.worker_id = CPGC.group_id * CP_GROUP_LEN + worker_id; strcpy(info.mmap_name, CPGS->workers[worker_id].sm_obj.mmap_name); info.ping_pid = CPGS->ping_workers->pid; info.max = CPGC.max_read_len; CPGS->workers[worker_id].CPid = CPid; return cpWrite(fd, &info, sizeinfo); }
static int cpReactor_client_receive(int fd) { int n; int event_size = sizeof (cpTcpEvent); char data[event_size]; //非ET模式会持续通知 n = cpNetRead(fd, data, event_size); cpConnection *conn = &(CPGS->conlist[fd]); if (n > 0) { cpTcpEvent *event = (cpTcpEvent*) data; // cpLog("evetn %d con %d",event->type,conn->release); if (event->type == CP_TCPEVENT_GET && conn->release == CP_FD_NRELEASED) {//动作是获得连接但是状态是未释放,父进程连的然后在子进程和父进程中都用这个连接,会出现这种情况 cpMasterInfo info = {0}; int sizeinfo = sizeof (info); info.worker_id = -1; //define it return cpWrite(fd, &info, sizeinfo); } if (event->type == CP_TCPEVENT_RELEASE) { return cpReactor_client_release(fd); } if (conn->release == CP_FD_RELEASED) {//之前释放了,或者刚进来的连接,需要争抢(这个状态不需要加锁,每个con的fd只分配给一个线程) cpTryGetWorkerId(conn, data, fd, n); if (conn->release == CP_FD_WAITING) { return 1; } if (conn->release == CP_FD_RELEASED) {//争抢失败,fork失败 char tmp[sizeof (CP_TOO_MANY_CON_ERR) + sizeof (CP_CLIENT_EOF_STR)] = {CP_TOO_MANY_CON_ERR}; strcat(tmp, CP_CLIENT_EOF_STR); return cpWrite(fd, tmp, strlen(tmp)); } } return MasterSend2Client(fd, conn->worker_id, event->ClientPid); } else if (n == 0) { close_fd: return cpReactor_client_close(fd); } else {//需要检测errno来区分是EAGAIN还是ECONNRESET if (errno == EAGAIN) { return SUCCESS; } else if (errno == ECONNRESET) { goto close_fd; } else { cpLog("Read from socket[%d] fail. Error: %s [%d]", fd, strerror(errno), errno); return SUCCESS; } } return SUCCESS; }