加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
net_loop.c 8.58 KB
一键复制 编辑 原始数据 按行查看 历史
wusong 提交于 2021-01-18 19:36 . add all info fetch support
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <malloc.h>
#include <sys/select.h>
#include <netinet/in.h>
#include "common.h"
#include "logger.h"
#include "cmd_parse.h"
#include "msg_struct.h"
const magic_type msg_magic = 0xA5A5;
#include "db_op.h"
#include "net_loop.h"
#define dumpmem(start, size) \
do{ \
for(int i = 0 ; i<size; i++) \
{\
printf("%02x\n", *((char *)start + i)); \
}\
}while(0)
int sfd = -1;
fd_set readfds;
#define MSG_MAX_LEN 4096
typedef struct sock_info_s
{
int sock_fd;
short buf_pos;
short need_len; //数据还需要接收多少个字节,如果报文头没有收到该值时0
short header_len;
char rbuf[MSG_MAX_LEN];
} sock_info_t;
sock_info_t *socklist[FD_SETSIZE] = {0};
int maxfd;
sock_info_t *alloc_sock_info()
{
return (sock_info_t *)malloc(sizeof(sock_info_t));
}
void del_fd( int fd)
{
FD_CLR(fd, &readfds);
}
typedef enum
{
ERROR_MEM = 1,
ERROR_ACCEPT,
ERROR_SOCK,
SOCK_HEADER_MORE,
SOCK_DATA_MORE
}RET_TYPE;
RET_TYPE accept_client()
{
struct sockaddr_in caddr;
bzero(&caddr, sizeof(caddr));
unsigned int len = 0;
int cfd = accept(sfd, (struct sockaddr *)&caddr, &len);
if (cfd < 0)
{
LOG_ERROR("accept error : %s", strerror(errno));
return ERROR_ACCEPT;
}
LOG_INFO("accept %d", cfd);
sock_info_t * sock_info = alloc_sock_info();
if (!sock_info)
{
close(cfd);
return ERROR_MEM;
}
sock_info->sock_fd = cfd;
sock_info->need_len = 0;
sock_info->buf_pos = 0;
sock_info->header_len = 0;
socklist[cfd] = sock_info;
FD_SET(cfd, &readfds);
maxfd = max(maxfd, cfd);
return 0;
}
RET_TYPE recv_data(int cfd, void *buf, int size)
{
int recv_bytes = 0;
recv_bytes = recv(cfd, buf, size, 0);
LOG_DEBUG("recv bytes : %d\n", recv_bytes)
dumpmem(buf, recv_bytes);
if (recv_bytes <= 0)
{
if (errno == EINTR || errno == EINPROGRESS
|| errno == EAGAIN)
{
recv_bytes = 0;
}
else
{
return ERROR_SOCK;
}
}
return recv_bytes;
}
RET_TYPE recv_header(sock_info_t * sock_info)
{
//recv msg header
int ret = recv_data(sock_info->sock_fd, sock_info->rbuf + sock_info->header_len,
MSG_HEADER_SIZE -sock_info->header_len);
// LOG_DEBUG("%#x, header len %d", sock_info->rbuf, ret)
if (ret == ERROR_SOCK)
{
return ERROR_SOCK;
}
sock_info->header_len += ret;
if (sock_info->header_len >= MSG_MAGIC_SIZE)
{
// 处理错误的包头标志
if (memcmp(sock_info->rbuf, MSG_MAGIC, MSG_MAGIC_SIZE))
{
//ignore these wrong bytes
memmove(sock_info->rbuf, sock_info->rbuf + MSG_MAGIC_SIZE, MSG_MAGIC_SIZE);
sock_info->header_len -= MSG_MAGIC_SIZE;
//want recv more else
LOG_DEBUG("invalid header");
return SOCK_HEADER_MORE;
}
LOG_DEBUG("recv a header")
}
if (sock_info->header_len < MSG_HEADER_SIZE)
{
//want recv more else
return SOCK_HEADER_MORE;
}
msg_header_t *msg_header = (msg_header_t *)sock_info->rbuf;
msg_header->len = ntohs(msg_header->len);
msg_header->type = ntohs(msg_header->type);
LOG_DEBUG("type : %#x", msg_header->type);
LOG_DEBUG("len : %#x", msg_header->len);
if (msg_header->len > (MSG_MAX_LEN - MSG_HEADER_SIZE))
{
LOG_ERROR("wrong msg len field");
sock_info->header_len = 0;
sock_info->buf_pos = 0;
sock_info->need_len = 0;
return SOCK_HEADER_MORE;
}
sock_info->need_len = msg_header->len;
sock_info->buf_pos += MSG_HEADER_SIZE;
return SOCK_DATA_MORE;
}
RET_TYPE unpack_client_msg(msg_header_t *msg_header, sock_info_t * sock_info)
{
int msg_ret = ERROR_SOCK;
LOG_DEBUG("msg type : %u", msg_header->type);
// dumpmem(msg_header, sizeof(*msg_header));
LOG_DEBUG("msg type : %u", msg_header->type);
switch (msg_header->type)
{
case MSG_LOGIN:
{
msg_login_t *login_info = (msg_login_t *) (msg_header+1);
LOG_INFO("login --- %s, %s", login_info->username, login_info->passwd);
char sbuf[MSG_HEADER_SIZE + 2];
memset(sbuf, 0, MSG_HEADER_SIZE + 2);
msg_header_t *msg_res = (msg_header_t *)sbuf;
msg_res->magic = msg_magic;
msg_res->type = MSG_LOGIN_RSP;
msg_res->len = 2;
memcpy(sbuf+MSG_HEADER_SIZE, "OK", 2);
int sret = send(sock_info->sock_fd, sbuf, sizeof(sbuf), 0);
if (sret < 0)
{
LOG_ERROR("send to %d resp login fail", sock_info->sock_fd);
msg_ret = ERROR_SOCK;
}
msg_ret = SOCK_HEADER_MORE;
break;
}
case MSG_GET_INFO:
{
msg_get_info_t * get_info = (msg_get_info_t *)(msg_header +1);
msg_rsp_info_t * rsp = get_staff_info(get_info);
if (NULL == rsp)
{
LOG_ERROR("get staff error");
msg_ret = ERROR_SOCK;
}
char sbuf[MSG_HEADER_SIZE];
msg_header_t *msg_res = (msg_header_t *)sbuf;
msg_res->magic = msg_magic;
msg_res->type = MSG_GET_INFO_RSP;
msg_res->len = sizeof(msg_rsp_info_t) + rsp->num * sizeof(staff_info_t);
int sret = send(sock_info->sock_fd, msg_res, sizeof(msg_header_t), 0);
if (sret < 0)
{
LOG_ERROR("send to %d resp login fail", sock_info->sock_fd);
msg_ret = ERROR_SOCK;
}
sret = send(sock_info->sock_fd, rsp, msg_res->len, 0);
if (sret < 0)
{
LOG_ERROR("send to %d resp login fail", sock_info->sock_fd);
msg_ret = ERROR_SOCK;
}
else
{
msg_ret = SOCK_HEADER_MORE;
}
free(rsp);
break;
}
default:
LOG_ERROR("not supported msg type %d", msg_header->type);
return ERROR_SOCK;
break;
}
return msg_ret;
}
RET_TYPE recv_from_client(int cfd)
{
sock_info_t * sock_info = socklist[cfd];
if (sock_info->need_len == 0)
{
return recv_header(sock_info);
}
LOG_DEBUG("RECV HEADER");
//recv msg header
int ret = recv_data(sock_info->sock_fd, sock_info->rbuf + sock_info->buf_pos,
sock_info->need_len);
if (ret == ERROR_SOCK)
{
return ERROR_SOCK;
}
sock_info->need_len -= ret;
if (0 != sock_info->need_len)
{
return SOCK_DATA_MORE;
}
msg_header_t *msg_header = (msg_header_t *)sock_info->rbuf;
int msg_ret = unpack_client_msg(msg_header, sock_info);
//处理消息
sock_info->header_len = 0;
sock_info->buf_pos = 0;
sock_info->need_len = 0;
return msg_ret;
}
void select_loop(void)
{
int loop_max;
maxfd = sfd;
fd_set tempfds;
FD_ZERO(&readfds);
FD_SET(sfd, &readfds);
int ret;
while (1)
{
tempfds = readfds;
LOG_DEBUG("select ");
ret = select(maxfd + 1, &tempfds, NULL, NULL, NULL);
LOG_DEBUG("select count %d", ret);
if (ret < 0)
{
LOG_ERROR("epoll wait error : %s", strerror(errno));
return ;
}
loop_max = maxfd + 1;
for(int i = 3;(i < loop_max); i ++)
{
if (!FD_ISSET(i,&tempfds))
{
continue;
}
if (i == sfd)
{
if (0 != accept_client())
{
LOG_ERROR("accept client error");
continue;
}
}
else
{
LOG_INFO("client data");
if (ERROR_SOCK == recv_from_client(i))
{
LOG_ERROR("sock occure error,close it")
close(i);
FD_CLR(i, &readfds);
// seek second max fd, clean this fd
if (maxfd == i)
{
int sec_fd = 0;
for (int j = 0; j < maxfd; j++)
{
if(FD_ISSET(j, &readfds))
{
sec_fd = j;
}
}
maxfd = sec_fd;
}
sock_info_t * sock_info = socklist[i];
free(sock_info);
socklist[i] = NULL;
}
LOG_DEBUG("client data end")
}
}
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化