做服务无非就那几步,启动端口监听、接收请求数据、分配资源受理,反馈应答数据,关闭释放资源。一个优秀的服务端实现要考虑并发处理和对共享资源控制还是要费点心思的。Linux下提供了一个基于xinetd服务的低成本小制作解决方案,用起来超方便,优缺点放最后总结欢迎点评。
0001: /****************************************/
0002: /* Author: gong_libin */
0003: /* Date: 2000_01_01 */
0004: /* File: GDeamon.c */
0005: /****************************************/
0006:
0007: /**
0008: * /etc/xinetd.d/GDeamon
0009: * service GDeamon
0010: * {
0011: * flags = REUSE
0012: * socket_type = stream
0013: * wait = no
0014: * user = root
0015: * server = /usr/bin/GDeamon
0016: * log_on_failure += USERID
0017: * disable = no
0018: * }
0019: *
0020: * /etc/services
0021: * GDeamon 321/tcp # The GDeamon Protocol
0022: */
0023:
0024: #include <stdio.h>
0025: #include <stdlib.h>
0026: #include <string.h>
0027: #include <unistd.h>
0028: #include <fcntl.h>
0029: #include <time.h>
0030:
0031: #define G_STDIN stdin
0032: #define G_STDOUT stdout
0033: #define G_STDERR stderr
0034:
0035: #define G_TIMOUT 10
0036: #define G_PACKET 1024
0037: #define G_RESULT G_PACKET * G_PACKET
0038:
0039: int main(int argc, char* argv[])
0040: {
0041: FILE* pstPipe = NULL;
0042: time_t ulTime = time(NULL);
0043: char szPacket[G_PACKET] = {0};
0044: char szResult[G_RESULT] = {0};
0045: int iCount = 0, iTotal = 0, iLength = 0;
0046:
0047: close(fileno(G_STDERR));
0048: fcntl(fileno(G_STDIN), F_SETFL, O_NONBLOCK);
0049:
0050: if (fread(&iLength, sizeof(int), 1, G_STDIN) > 0) {
0051: while (iTotal < iLength) {
0052: if (time(NULL) - ulTime > G_TIMOUT) {
0053: printf("数据接收超时");
0054: break;
0055: }
0056: if ((iCount = fread(&szPacket[iTotal], sizeof(char), G_PACKET - iTotal, G_STDIN)) > 0) {
0057: iTotal += iCount;
0058: }
0059: }
0060: if (iLength == strlen(szPacket)) {
0061: if (NULL != (pstPipe = popen(szPacket, "r"))) {
0062: if (NULL != fgets(szResult, G_PACKET, pstPipe)) {
0063: printf("%s", szResult);
0064: }
0065: pclose(pstPipe);
0066: }
0067: else {
0068: printf("命令执行失败");
0069: }
0070: }
0071: else {
0072: printf("数据长度错误");
0073: }
0074: }
0075:
0076: return 0;
0077: }
009-018定义配置文件/etc/xinetd.d/Gdeamon,通知系统允许端口复用、传输层是TCP协议、不等待进程终止、进程归属root用户、执行程序存放路径等信息。
021行追加到/etc/services文件中,通知系统传输层协议类型和监听端口及服务名称。
047行关闭错误输出免得添乱,48行设置标准输入为非阻塞模式。
050行从标准输入读取一个整形,在这个用例中这个整形用于表示后面数据的长度。
051-059行根据上面整形值循环读取数据直到读取完毕或超时为止。
060行判断读取数据的完整性。
061-069把用户发送过来的指令提交系统执行并通过管道获取执行结果。
063行把执行结果通过标准输出返回。
完事了就这么简单省心省力满足并发处理资源回收完全不操心,监听端口监听到连接的时候会fork子进程,同时把子连接的套接字传下去,并把读写操作重定向到标准输入输出上,真欣赏这种简单粗暴而又行之有效的做法。用例仅供参考,至于通信协议和异常机制没做过多处理,需要自己加吧。
优点:开发便利快捷,重点可放在业务流的上,处理并发量不大逻辑不复杂的接口半天时间连调带测足够;不仅支持tcp协议也支持udp协议,可以节省大量服务框架代码的开发工作量;
缺点:并发量一大力不从心,响应不够快速高效,在线调测不够方便;
今晚有雨出门带伞~