/****************************************************************************** **函数名称: rtrd_rsvr_sck_creat **功 能: 创建套接字对象 **输入参数: ** rsvr: 接收服务 ** req: 添加套接字请求 **输出参数: NONE **返 回: 套接字对象 **实现描述: 创建套接字对象, 并依次初始化其成员变量 **注意事项: 套接字关闭时, 记得释放空间, 防止内存泄露! **作 者: # Qifeng.zou # 2015.06.11 # ******************************************************************************/ static rtrd_sck_t *rtrd_rsvr_sck_creat(rtrd_rsvr_t *rsvr, rtmq_cmd_add_sck_t *req) { void *addr; list_opt_t opt; rtrd_sck_t *sck; /* > 分配连接空间 */ sck = calloc(1, sizeof(rtrd_sck_t)); if (NULL == sck) { log_error(rsvr->log, "Alloc memory failed!"); CLOSE(req->sckid); return NULL; } memset(sck, 0, sizeof(rtrd_sck_t)); sck->fd = req->sckid; sck->nodeid = -1; sck->sid = req->sid; sck->ctm = time(NULL); sck->rdtm = sck->ctm; sck->wrtm = sck->ctm; snprintf(sck->ipaddr, sizeof(sck->ipaddr), "%s", req->ipaddr); do { /* > 创建发送链表 */ memset(&opt, 0, sizeof(opt)); opt.pool = (void *)NULL; opt.alloc = (mem_alloc_cb_t)mem_alloc; opt.dealloc = (mem_dealloc_cb_t)mem_dealloc; sck->mesg_list = list_creat(&opt); if (NULL == sck->mesg_list) { log_error(rsvr->log, "Create list failed!"); break; } /* > 申请接收缓存 */ addr = (void *)calloc(1, RTMQ_BUFF_SIZE); if (NULL == addr) { log_error(rsvr->log, "errmsg:[%d] %s!", errno, strerror(errno)); break; } rtmq_snap_setup(&sck->recv, addr, RTMQ_BUFF_SIZE); return sck; } while (0); /* > 释放套接字对象 */ rtrd_rsvr_sck_free(rsvr, sck); return NULL; }
/****************************************************************************** **函数名称: rtrd_rsvr_dist_data **功 能: 分发连接队列中的数据 **输入参数: ** ctx: 全局对象 ** rsvr: 接收服务 **输出参数: NONE **返 回: 0:成功 !0:失败 **实现描述: **注意事项: **作 者: # Qifeng.zou # 2015.06.02 # ******************************************************************************/ static int rtrd_rsvr_dist_data(rtrd_cntx_t *ctx, rtrd_rsvr_t *rsvr) { #define RTRD_POP_MAX_NUM (1024) int len, idx, num; queue_t *sendq; void *addr; void *data[RTRD_POP_MAX_NUM]; rtmq_frwd_t *frwd; list_opt_t opt; rtrd_sck_t *sck; _conn_list_t cl; rtmq_header_t *head; sendq = ctx->sendq[rsvr->id]; while (1) { /* > 弹出队列数据 */ num = MIN(queue_used(sendq), RTRD_POP_MAX_NUM); if (0 == num) { break; } num = queue_mpop(sendq, data, num); if (0 == num) { continue; } log_trace(ctx->log, "Multi-pop num:%d!", num); /* > 逐条处理数据 */ for (idx=0; idx<num; ++idx) { frwd = (rtmq_frwd_t *)data[idx]; /* > 查找发送连接 */ memset(&opt, 0, sizeof(opt)); opt.pool = (void *)NULL; opt.alloc = (mem_alloc_cb_t)mem_alloc; opt.dealloc = (mem_dealloc_cb_t)mem_dealloc; cl.nodeid = frwd->dest; cl.list = list_creat(&opt); if (NULL == cl.list) { queue_dealloc(sendq, data[idx]); log_error(rsvr->log, "Create list failed!"); continue; } list2_trav(rsvr->conn_list, (list2_trav_cb_t)rtrd_rsvr_get_conn_list_by_nodeid, &cl); if (0 == cl.list->num) { queue_dealloc(sendq, data[idx]); list_destroy(cl.list, NULL, mem_dummy_dealloc); log_error(rsvr->log, "Didn't find connection by nodeid [%d]!", cl.nodeid); continue; } sck = (rtrd_sck_t *)list_fetch(cl.list, rand()%cl.list->num); /* > 设置发送数据 */ len = sizeof(rtmq_header_t) + frwd->length; addr = calloc(1, len); if (NULL == addr) { queue_dealloc(sendq, data[idx]); list_destroy(cl.list, NULL, mem_dummy_dealloc); log_error(rsvr->log, "Alloc memory from slab failed!"); continue; } head = (rtmq_header_t *)addr; head->type = frwd->type; head->nodeid = frwd->dest; head->flag = RTMQ_EXP_MESG; head->checksum = RTMQ_CHECK_SUM; head->length = frwd->length; memcpy(addr+sizeof(rtmq_header_t), data[idx]+sizeof(rtmq_frwd_t), head->length); queue_dealloc(sendq, data[idx]); /* > 放入发送链表 */ if (list_rpush(sck->mesg_list, addr)) { FREE(addr); log_error(rsvr->log, "Push input list failed!"); } list_destroy(cl.list, NULL, mem_dummy_dealloc); /* 无需是否结点数据空间 */ } } return RTMQ_OK; }
int main(void) { int sev_fd,cli_fd,cli_addr_len; //客户端、服务器端描述符,客户端地址长度 char *ifo; //错误提示 struct sockaddr_in cli_addr,sev_addr; //客户端、服务器地址结构 fd_set readfds,testfds; //监控集合 int cli_count = 0,recv_count,result; //连接数目、收到字节数目、发生时间数目 onlinelist *pHead, *pNew, *pTemp, *pTar; //链表操作 datapack buf; //数据包 //开启服务,添加系统日志 ifo = "The server is strart"; add_syslog_sev(ifo); //初始化socket sev_fd = socket(AF_INET, SOCK_STREAM, 0); if (sev_fd < 0){ ifo = strerror(errno); add_errorlog_sev(ifo); return EXIT_FAILURE; } int on = 1; if (setsockopt(sev_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1){ ifo = strerror(errno); add_errorlog_sev(ifo); return EXIT_FAILURE; } //初始化server端IP; sev_addr.sin_family = AF_INET; sev_addr.sin_port = htons(2489); sev_addr.sin_addr.s_addr = htonl(INADDR_ANY); //绑定端口 if (bind(sev_fd,(struct sockaddr *)&sev_addr,sizeof(sev_addr)) == -1){ ifo = strerror(errno); add_errorlog_sev(ifo); return EXIT_FAILURE; } //监听 if (listen(sev_fd,40) == -1){ ifo = strerror(errno); add_errorlog_sev(ifo); return EXIT_FAILURE; } //创建一条链表用于存储连接上的用户套接字描述符 list_creat(pHead,onlinelist); FD_ZERO(&readfds); FD_SET(sev_fd,&readfds); pNew = (onlinelist *)malloc(sizeof(onlinelist)); pNew->sock = sev_fd; add_tial(pHead, pNew, onlinelist); cli_count++; while(1){ testfds = readfds; result = select(100,&testfds,NULL,NULL,NULL); if (result == -1){ ifo = strerror(errno); add_errorlog_sev(ifo); return EXIT_FAILURE; } if (result > 0){ pTemp = pHead->pNext; while(pTemp != NULL){ if (FD_ISSET(pTemp->sock,&testfds)){ if (pTemp->sock == sev_fd){ //接受连接 cli_addr_len = sizeof(cli_addr); cli_fd = accept(sev_fd,(struct sockaddr *)&cli_addr,&cli_addr_len); if (cli_fd < 0){ ifo = strerror(errno); add_errorlog_sev(ifo); return EXIT_FAILURE; } FD_SET(cli_fd, &readfds); pNew = (onlinelist *)malloc(sizeof(onlinelist)); pNew->sock = cli_fd; strcpy(pNew->ip, inet_ntoa(cli_addr.sin_addr)); add_tial(pHead, pNew, onlinelist); cli_count++; } else{ memset(&buf,0,sizeof(buf)); recv_count = recv(pTemp->sock, &buf, sizeof(buf),0); if (recv_count == 0){ cli_count--; close(pTemp->sock); FD_CLR(pTemp->sock,&readfds); userlogout_sev(pTemp->id, pTemp->ip); pTar = pTemp; pTemp = pTemp->pNext; del_node(pHead, pTar, onlinelist); if (pTemp == NULL) break; } else{ analyzedatapack(&buf, pTemp->sock, pTemp->ip, pHead, pTemp); } } } pTemp = pTemp->pNext; } } } close(sev_fd); //关闭服务,添加系统日志 ifo = "The server is close"; add_syslog_sev(ifo); return EXIT_SUCCESS; }
static void list_test() { list_creat(); list_print(); // this is WRONG... printf("*****WRONG************\n"); node* item; node** ptr; for (ptr = &node::first; (item = *ptr); ptr = &(*ptr)->next) { printf("item: %p %p %d\n", item, item->next, item->data); if (item->data == 2) list_remove(ptr); } list_print(); printf("**********************\n"); // this is WRONG... list_destroy(); list_creat(); list_print(); printf("*****WRONG************\n"); item = node::first; ptr = &node::first; do { printf("item: %p %p %d\n", item, item->next, item->data); if (item->data == 2) list_remove(ptr); ptr = &(*ptr)->next; } while ((item = *ptr)); list_print(); printf("**********************\n"); // this is WRONG... list_destroy(); list_creat(); list_print(); printf("*****WRONG************\n"); ptr = &node::first; while ((item = *ptr)) { printf("item: %p %p %d\n", item, item->next, item->data); if (item->data == 3) list_remove(ptr); ptr = &(*ptr)->next; } list_print(); printf("**********************\n"); // this is OK... list_destroy(); list_creat(); list_print(); printf("*****OK***************\n"); ptr = &node::first; while ((item = *ptr)) { printf("item: %p %p %d\n", item, item->next, item->data); if (item->data == 3) { list_remove(ptr); continue; } ptr = &(*ptr)->next; } list_print(); printf("**********************\n"); // this is OK... list_destroy(); list_creat(); list_print(); printf("*****OK***************\n"); item = node::first; ptr = &node::first; do { printf("item: %p %p %d\n", item, item->next, item->data); if (item->data == 2) { list_remove(ptr); continue; } ptr = &(*ptr)->next; } while ((item = *ptr)); list_print(); printf("**********************\n"); exit(0); }