关于多线程,多消息队列做一个UDP并发服务器
首先用epoll检测套接字状态,虽然UDP只有一个套接字,但是用了epoll可以大大降低cpu的使用,得到数据后,想用一个线程池+多个消息队列来处理,现在只能做到单线程+单个消息队列,求高人指点:
heart_beat_packet.h:
struct MSHeartBeatUDPPacket
{
char SN[32];
int ms_id;
int tag;
char localIP[16];
char flag;
char reserved[67];
}__attribute__((packed));
struct RSP_MSHeartBeatUDPPacket
{
char SN[32];
int tag;
int ms_id;
char reserved[64];
}__attribute__((packed));
memery_struct.h:
struct momery_struct
{
char localIP[16];
char router_ip[16];
int port;
int seconds;
}__attribute__((packed));
struct res_mom
{
char SN[32];
char localIP[16];
char router_ip[16];
int tag;
int port;
int ms_id;
char flag;
char reserved[3];
}__attribute__((packed));
struct block_queue
{
struct res_mom cli_address;
struct sockaddr_in client;
long size;
struct list_head list;
}__attribute__((packed));
server.c:
#include <mysql/mysql.h>
#include "list.h"
#include <pthread.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/msg.h>
#include <time.h>
#include <pthread.h>
#include <sys/time.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "heart_beat_packet.h"
#include "global.h"
#include "momery_struct.h"
#include <sys/epoll.h>
#define MAX_EVENTS 5000
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
struct tm *timeinfo;
struct momery_struct user[10000];
int ep,counter = 0;
MYSQL mysql;
MYSQL_RES *res;
MYSQL_ROW row;
char query[512] = {0};
int listenfd;
char *hostname = NULL;
char *username = NULL;
char *password = NULL;
char *database = NULL;
struct list_head head;
void setnonblocking(int sock)
{
int opts;
opts = fcntl(sock, F_GETFL);
if (opts < 0)
{
perror("fcntl(sock,GETFL)");
exit(1);
}
opts = opts | O_NONBLOCK;
if (fcntl(sock, F_SETFL, opts) < 0)
{
perror("fcntl(sock, SETFL, opts)");
exit(1);
}
}
int refreshtime()
{
time_t nowtime;
time(&nowtime);
timeinfo = localtime(&nowtime);
return nowtime;
}
void scan(void *cli_address, void *client)
{
struct res_mom *cli_addr = (struct res_mom *)cli_address;
struct sockaddr_in *cli = (struct sockaddr *)client;
if (cli_addr -> ms_id == 0)
{
//printf("buf.SN: %s\n", cli_addr -> SN);
db_insert(cli_addr, cli);
}
else if(check_momery(cli_addr) == 0)
{
//printf("check momery\n");
db_update(cli_addr, cli);
}
else
{
//printf("momery update\n");
momery_update(cli_addr,cli);
}
/*for(count = 0; count < 10000; count++)
{
if (user[count].seconds != 0)
{
if ((refreshtime() - user[count].seconds) >= 60)
db_set_flag(count, cli_addr);
}
}*/
}
int handle_message(void *cli_addr, void *client)
{
return insert_queue(cli_addr, client);
}
int insert_queue(void *cli_addr, void *client)
{
struct block_queue *b = (struct block_queue *)malloc(sizeof(struct block_queue));
memcpy(&(b -> cli_address), (struct res_mom *)cli_addr, 80);
memcpy(&(b -> client), (struct sockaddr_in *)client, sizeof(struct sockaddr_in));
pthread_mutex_lock(&mutex);
if (counter > 1000)
return 1;
else
counter++;
list_add_tail(&b->list, &head);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
return 0;
}
static void block_que()
{
struct res_mom cli_addr;
struct sockaddr_in client;
struct block_queue *head_node;
for( ; ;)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
if (list_empty(&head))
{
pthread_mutex_unlock(&mutex);
continue;
}
else
{
memset(&cli_addr, 0 , sizeof(cli_addr));
head_node = list_entry(head.next, struct block_queue, list);
memcpy(&cli_addr, &(head_node -> cli_address), 80);
memcpy(&client, &(head_node -> client), sizeof(client));
list_del(&head_node -> list);
free(head_node);
counter--;
}
pthread_mutex_unlock(&mutex);
scan(&cli_addr, &client);
}
}
static int init_threads()
{
size_t i = 0;
pthread_t child_thread;
pthread_attr_t child_thread_attr;
pthread_attr_init(&child_thread_attr);
pthread_attr_setdetachstate(&child_thread_attr, PTHREAD_CREATE_DETACHED);
if (pthread_create(&child_thread, &child_thread_attr, (void *)block_que, NULL) < 0)
{
SYSLOG("pthread_create Failed: %s\n", strerror(errno));
return 1;
}
else
{
return 0;
}
}
int main(int argc, char *argv[])
{
memset(user, 0 , sizeof(struct momery_struct)*10000);
pthread_t id;
int sockfd, i, nfds, g_epollfd;
struct sockaddr_in serv;
int pid;
int port;
int now_seconds = 0;
int count = 0;
int serv_port = 9000;
int opt = -1, daemon = 0;
mysql_init(&mysql);
mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "mysql");
if (!mysql_real_connect(&mysql, "localhost", "root", "123456", "zhudewei", 0 , NULL, 0))
{
SYSLOG("can not connect to mysql\n");
exit(-1);
}
INIT_LIST_HEAD(&head);
struct epoll_event ev, events[MAX_EVENTS];
g_epollfd = epoll_create(MAX_EVENTS);
listenfd = socket(AF_INET, SOCK_DGRAM, 0);
if (listenfd < 0) {
perror("socket");
exit(1);
}
setnonblocking(listenfd);
memset(&serv,0,sizeof(serv));
serv.sin_family = AF_INET;
serv.sin_port = htons(serv_port);
serv.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(listenfd, (struct sockaddr*)&serv, sizeof(serv)) < 0) {
perror("bind");
exit(1);
}
if (init_threads() == 0)
{
SYSLOG("Sucess init threads\n");
}
ev.data.fd = listenfd;
ev.events = EPOLLIN | EPOLLET;
epoll_ctl(g_epollfd, EPOLL_CTL_ADD, listenfd, &ev);
now_seconds = refreshtime();
int curfds = 1;
while (1) {
if((refreshtime() - now_seconds) >= 60)
{
now_seconds = refreshtime();
for(count = 0; count < 10000; count++)
{
if (user[count].seconds != 0)
{
if ((refreshtime() - user[count].seconds) >= 60)
db_set_flag(count);
}
}
}
nfds = epoll_wait(g_epollfd, events, MAX_EVENTS, -1);
if (nfds == 0)
continue;
else if(nfds < 0)
{
SYSLOG("epoll_wait error\n");
}
else
{
for (i = 0; i < nfds; i++)
{
if (events[i].events & EPOLLIN)
{
struct MSHeartBeatUDPPacket buf;
struct sockaddr_in cli;
socklen_t addrlen;
int n;
struct res_mom cli_address;
struct RSP_MSHeartBeatUDPPacket packet;
memset(&cli_address, 0, sizeof(struct res_mom));
memset(&packet, 0, sizeof(packet));
memset(&cli, 0, sizeof(cli));
addrlen = sizeof(cli);
memset(&buf, 0, sizeof(buf));
n = recvfrom(events[i].data.fd, &buf, sizeof(buf), 0, (struct sockaddr*)&cli, &addrlen);
if (n < 0)
continue;
memset(&cli_address, 0, sizeof(struct res_mom));
cli_address.port = cli.sin_port;
cli_address.ms_id = buf.ms_id;
cli_address.tag = buf.tag;
cli_address.flag = buf.flag;
strcpy(cli_address.localIP, buf.localIP);
strcpy(cli_address.router_ip, inet_ntoa(cli.sin_addr));
strcpy(cli_address.SN, buf.SN);
/*if (buf.flag & FLAG_MUST_REPLY)
{
packet.tag = buf.tag;
packet.ms_id = buf.ms_id;
strcpy(packet.SN, buf.SN);
sendto(events[i].data.fd, &packet, sizeof(packet), 0, (struct sockaddr*)&cli, sizeof(cli));
}*/
//int ret = 0;
if(handle_message(&cli_address, &cli) != 0)
SYSLOG("handler ret != 0");
/*if (buf.flag & FLAG_MUST_REPLY)
{
packet.tag = buf.tag;
packet.ms_id = buf.ms_id;
printf("buf.ms_id: %d\n",buf.ms_id);
strcpy(packet.SN, buf.SN);
sendto(events[i].data.fd, &packet, sizeof(packet), 0, (struct sockaddr*)&cli, sizeof(cli));
}*/
/*if (ret != 0 && errno != 11)
{
epoll_ctl(g_epollfd, EPOLL_CTL_DEL, events[i].data.fd, &ev);
curfds--;
}*/
}
}
}
}
close(listenfd);
mysql_close(&mysql);
}