做服務無非就那幾步,啟動端口監聽、接收請求資料、配置設定資源受理,回報應答資料,關閉釋放資源。一個優秀的服務端實作要考慮并發處理和對共享資源控制還是要費點心思的。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協定,可以節省大量服務架構代碼的開發工作量;
缺點:并發量一大力不從心,響應不夠快速高效,線上調測不夠友善;
今晚有雨出門帶傘~