免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345678
最近访问板块 发新帖
楼主: yulihua49
打印 上一主题 下一主题

[C] 多线程服务器,发现个问题,请高人解惑 [复制链接]

论坛徽章:
0
71 [报告]
发表于 2010-07-16 22:28 |只看该作者
4080个连接时进程使用了多少个fd看了没?可以调整小一点栈空间,能多支持一些线程。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
72 [报告]
发表于 2010-07-17 19:18 |只看该作者
本帖最后由 yulihua49 于 2010-07-18 12:55 编辑
4080个连接时进程使用了多少个fd看了没?可以调整小一点栈空间,能多支持一些线程。
没本 发表于 2010-07-16 22:28


共4096个fd,数据库池还要用,先前系统还用了好几个。超了一点,但没问题,超额的可以等前边的退出再进。
我对listen(sock,1000),有1000个都可以等着。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
73 [报告]
发表于 2010-07-20 14:30 |只看该作者
4080个连接时进程使用了多少个fd看了没?可以调整小一点栈空间,能多支持一些线程。
没本 发表于 2010-07-16 22:28



    解决了,线程池成功了,超稳定,超高效。释放连接时必须互斥锁。
不知为什么,线程池比多线程快许多。接入16300个链接很轻松。

论坛徽章:
0
74 [报告]
发表于 2010-07-20 18:20 |只看该作者
回复 73# yulihua49


    呵呵,恭喜你搞定服务器开发了。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
75 [报告]
发表于 2010-07-21 20:46 |只看该作者
回复  yulihua49


    呵呵,恭喜你搞定服务器开发了。
没本 发表于 2010-07-20 18:20



    同喜,可能将来细节上还有许多问题。
现在就有一个问题,C语言,一个线程fault,整个进程就down了。
我看JAVA,线程fault,进程不down,只down线程,C能做到吗?

论坛徽章:
0
76 [报告]
发表于 2010-07-22 08:56 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
77 [报告]
发表于 2010-07-22 10:10 |只看该作者
本帖最后由 yulihua49 于 2010-07-22 11:18 编辑
回复  yulihua49


    呵呵,恭喜你搞定服务器开发了。
没本 发表于 2010-07-20 18:20



    已经进行16000多连接,稳定。

超额的等待,等不起的挂断,服务器是不会死的。

不会发生当用户蜂拥而至时,服务器自杀的情况。

连上的进行协议验证,不符合协议(对不上黑话)的推出午门斩首,绝不会让这些反贼坏了江山。

只是在写服务时一定要注意线程安全,内存严谨,这个堡垒只能由内部攻破。

看看服务器框架的运用:
  1. #include <unistd.h>
  2. #include <ctype.h>
  3. #include <sys/resource.h>
  4. #include "../thread/thrsrv.h"

  5. extern int tpool_main(void (*conn_init)(T_Connect *,T_NetHead *),void (*quit)(int),void (*poolchk)(void),int sizeof_gda);
  6. extern void tpool_free(void);

  7. //定义服务函数
  8. srvfunc Function[]={
  9.         {login,"login"},        /*0 login.c */
  10.         {Echo,"Echo"},                  /*1*/
  11.         {Rexec, "Rexec"},
  12.         {GetFile,"GetFile"},
  13.         {PutFile,"PutFile"},
  14.         {Pwd,"Pwd"},        
  15.         {filels,"filels"},
  16.         {SQL_Select,"SQL_Select"},
  17.         {page_select,"page_select"},
  18.         {dui_svc,"dui_svc"},
  19.         {SQL_RPC,"SQL_RPC"},
  20.         {net_showlog,"net_showlog"},
  21.         {0,0}
  22. };

  23. void quit(int n)
  24. {
  25.         free_DB_pool();
  26.                 tpool_free();
  27.         ShowLog(0,"quit by %d",n);
  28.         exit(n);
  29. }
  30. //连接已收到,初始化连接器。
  31. void sc_init(T_Connect *conn,T_NetHead *head)
  32. {
  33. char *env;
  34. char cp[21];
  35. T_SRV_Var *sp;
  36. GDA *gp;
  37.         sp=(T_SRV_Var *) conn->Var;
  38.         gp=(GDA *)sp->var;
  39.         if(gp) *gp->ShowID=0;
  40.         env=getenv("SENDSIZE");
  41.         if(env && *env) {
  42.                 conn->MTU=atoi(env);
  43.         }
  44.         peeraddr(conn->Socket,cp);;
  45.         ShowLog(0,"tid %lu 连接:%s ",pthread_self(),cp);
  46. /* 在此设置事件处理 */
  47. //      connect->Event_proc=事件设置函数;

  48. }

  49. void FreeVar(void *data)
  50. {
  51. }

  52. static char my_showid[200];

  53. int main(int argc,char *argv[])
  54. {
  55. int ret;
  56. struct rlimit sLimit;
  57. char *p;

  58. //设置可以core dumpped
  59.         sLimit.rlim_cur = -1;
  60.         sLimit.rlim_max = -1;
  61.         ret=setrlimit(RLIMIT_CORE,(const struct rlimit *)&sLimit);

  62.         if(argc>1) ret=envcfg(argv[1]);

  63.         p=getenv("COL_TO_LOWER");
  64.         if(p && isdigit(*p)) col_to_lower=atoi(p);

  65.         sprintf(my_showid,"%s:%d",sc_basename(argv[0]),getpid());
  66.         Showid=my_showid;
  67.         ret=init_DB_pool();
  68.         if(ret) {
  69.                 ShowLog(1,"init_DB_pool:fail");
  70.                 return 1;
  71.         }
  72. //调用线程池服务器框架。它将根据客户请求的服务号调用服务函数。
  73.         tpool_main(sc_init,quit,dbpool_check,sizeof(GDA));//GDA用户自定义的上下文,告它一个尺寸,内部自己分配
  74.         quit(0);
  75. }
复制代码
服务函数的例子在4页31楼。

要想定义一个服务,只需;
按照框架规定的格式接受自变量和提供返回值,按照与客户端约定的流程处理业务。
函数原型加入公共头文件(../thread/thrsrv.h)。
加入服务器函数表。
Makefile里增加一个模块。

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
78 [报告]
发表于 2010-07-22 10:58 |只看该作者
已经进行16000多连接,稳定。

超额的等待,等不起的挂断,服务器是不会死的。

不会发生当用 ...
yulihua49 发表于 2010-07-22 10:10


关于数据库的服务,比较冗长,给一个简单点的例子。从客户端接收一个语句,(检查语句合法性),访问数据库,返回结果集。
  1. SQL_Select(T_Connect *connect,T_NetHead *NetHead)
  2. {
  3. char *rec=0;
  4. register int i;
  5. T_SRV_Var *srvp;
  6. T_SQL_Connect *SQL_Connect;
  7. int event;
  8.      srvp=(T_SRV_Var *)connect->Var;
  9.      SQL_Connect=&srvp->SQL_Connect;
  10.         event=NetHead->PROTO_NUM;
  11.         if(NetHead->data[strlen(NetHead->data)-1]=='|') {
  12.                 NetHead->data[strlen(NetHead->data)-1]=0;
  13.         }
  14.      ShowLog(5,"SQL Select:%s",NetHead->data);
  15.      i=SQL_Check_Stmt(NetHead->data);
  16.      if(i!=0){
  17.         sprintf(SQL_Connect->ErrMsg,"%s:invalid statment",NetHead->data);
  18.         ShowLog(1,"SQL_Select fail:%s",SQL_Connect->ErrMsg);
  19.              NetHead->PROTO_NUM=PutEvent(connect,NetHead->PROTO_NUM);
  20.         NetHead->ERRNO1=201;
  21.         NetHead->ERRNO2=0;
  22.         NetHead->O_NODE=ntohl(LocalAddr(0,0));
  23.         NetHead->PKG_REC_NUM=0;
  24.         NetHead->data=SQL_Connect->ErrMsg;
  25.         NetHead->PKG_LEN=strlen(NetHead->data);
  26.         i=SendPack(connect,NetHead);
  27.         return 0;
  28.      }
  29.         if(srvp->tid) {
  30.                 i=get_DB_connect(SQL_Connect,srvp->poolno);
  31.                 if(i) {
  32.                         sprintf(SQL_Connect->ErrMsg,"取连接池失败!,pool[%d],ret=%d",srvp->poolno,i);
  33.                         ShowLog(1,"%s:%s",__FUNCTION__,SQL_Connect->ErrMsg);
  34.                         NetHead->data=SQL_Connect->ErrMsg;
  35.                         NetHead->PKG_REC_NUM=0;
  36.                         NetHead->PKG_LEN=strlen(NetHead->data);
  37.                         NetHead->PROTO_NUM=PutEvent(connect,event);
  38.                         NetHead->ERRNO1=SQL_Connect->Errno;
  39.                         NetHead->ERRNO2=i;
  40.                         NetHead->O_NODE=ntohl(LocalAddr(connect->Socket,
  41.                                 SQL_Connect->ErrMsg+sizeof(SQL_Connect->ErrMsg)-20));
  42.                         SendPack(connect,NetHead);
  43.                         return 0;
  44.                 }
  45.         }

  46.      i=___SQL_Select__(SQL_Connect,NetHead->data,&rec,NetHead->PKG_REC_NUM);
  47.      if(i<=0) {
  48.              ShowLog(1,"SQL Select error: %d,%s",
  49.                 SQL_Connect->Errno,
  50.                 SQL_Connect->ErrMsg);
  51.         ___SQL_SendError(connect,NetHead->PROTO_NUM);
  52.         if(rec) free(rec);
  53.         return 0;
  54.      }
  55.         if(srvp->tid) release_DB_connect(SQL_Connect,srvp->poolno);
  56.      ShowLog(5,"SQL Select Success nROWS=%d",i);
  57.              NetHead->PROTO_NUM=PutEvent(connect,NetHead->PROTO_NUM);
  58.              NetHead->O_NODE=0;
  59.              NetHead->D_NODE=SQL_Connect->NativeError;
  60.              NetHead->ERRNO2=0;
  61.         NetHead->ERRNO1=0;
  62.              NetHead->PKG_REC_NUM=i;
  63.         NetHead->data=rec;
  64.              NetHead->PKG_LEN=strlen(NetHead->data);
  65.         SendPack(connect,NetHead);
  66.         if(rec) free(rec);
  67.         return 0;
  68. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP