关于多线程,多消息队列做一个UDP并发服务器

linyangwo2008 2010-10-28 01:45:52
首先用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);
}

...全文
679 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
linyangwo2008 2010-10-28
  • 打赏
  • 举报
回复
再补充下,不是单线程加消息队列不可以,而是因为cpu是多核,所以如果要发挥多核的优势,用N线程+N消息队列很好!但我不知道怎么去实现!
linyangwo2008 2010-10-28
  • 打赏
  • 举报
回复
部分具体函数功能就不写了,帖子过长
内容概要:本文提出了一种基于粒子群优化算法(PSO)的风光储能微电网日前经济调度模型,创新性地引入需求响应机制,以实现系统运行成本最小化为目标。该模型综合考虑风力发电、光伏发电、储能系统及可调节负荷的运行特性,构建了包含电力供需平衡、设备出力能力、储能容量约束在内的完整数学模型,并通过Python编程实现PSO算法求解,有效提升了新能源消纳水平并降低了购电成本与运行费用。研究不仅实现了多能源协调优化调度,还为高比例可再生能源接入背景下的微电网经济运行提供了可行的技术路径。; 适合人群:具备一定电力系统基础知识和Python编程能力的科研人员、研究生及从事新能源微电网优化调度相关工作的工程技术人员。; 使用场景及目标:①研究含高比例可再生能源的微电网经济调度问题;②掌握粒子群算法在电力系统优化中的建模与应用方法;③开展计及需求响应的多能源协同调度仿真分析,探索用户侧灵活性资源参与系统优化的潜力。; 阅读建议:建议读者结合提供的Python代码深入理解算法实现细节,重点关注目标函数构建、约束条件处理及PSO参数设置,可进一步拓展至其他智能优化算法对比分析,或引入碳排放、电压稳定性等多目标优化维度进行深化研究。
打开链接下载源码: https://pan.quark.cn/s/a4b39357ea24 修改自己电脑的OEM信息及产品ID 本文主要讲述了如何修改自己电脑的OEM信息及产品ID,以拥有一个跟正版一样的显示效果。 文章共分为两种方法介绍了如何修改OEM信息,分别是通过软件进行修改和手动修改注册表信息。 方法一:通过软件进行修改 软件可以帮助用户快速地修改OEM信息,使用非常简单,只要选择想要修改到的厂商就可以了。 然后在高级选项中选择是否要在开始菜单中显示OEM图标和厂商信息。 通过以上步骤,用户的电脑就能拥有一个跟OEM版本一样的信息了! 方法二:手动修改注册表信息 手动修改注册表信息需要用户具备一定的计算机知识和技能。 用户需要上网搜索一张OEM logo或者从另外一台电脑上复制一张logo到自己的电脑上。 然后,用户需要找一个图标文件命名为 OEMLINKICON.ICO,作为支持信息之前的那个小图标。 接下来,用户需要修改个人信息,打开注册表编辑器,搜索到“RegisteredOwner”和“RegisteredOrganization”,这两样分别指注册者姓名和注册者单位,修改成自己的就可以了。 然后,用户需要制作“厂商、电脑型号”和“技术支持信息”(如果你的电脑有的话)。 新建一个文本文档,输入[Version]Microsoft Windows Whistler EditionWinVer=5.01[General]Manufacturer=xx(厂商)有限公司Model=xx 系列电脑[Support Information],这是“技术支持信息”的内容。 Line1=""Line2=""Line3=""Li...

23,223

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧