Linux網絡編程服務器模型選擇之循環服務器

轉載:http://www.cnblogs.com/lizhenghn/p/3617608.html

在網絡程序里面,通常都是一個服務器處理多個客戶機,為了出個多個客戶機的請求,服務器端的程序有不同的處理方式。本節開始介紹Linux下套接字編程的服務器模型選擇,主要包括循環服務器模型、并發服務器模型、IO復用服務器模型等,這也是我們常見的幾種網絡服務器模型。其中基本可以分為兩大類,

1. 循環服務器:循環服務器在同一時刻只能響應一個客戶端的請求,是比較簡單的一種模型;

2. 并發服務器:并發服務器在同一時刻可以響應多個客戶端的請求,這里面又有很多分類,接下來會逐步介紹;

循環服務器模型

???? 循環服務器是指對于客戶端的請求和連接,服務器逐個進行處理,處理完一個連接后再處理下一個連接,屬于串行處理方式,結構比較簡單。該模型的算法過程如下:

復制代碼
/* UDP循環服務器模型 */ socket(); bind(); while(true)
{
   recvfrom(); process(); sendto(); 
} close();
復制代碼
復制代碼
/* TCP循環服務器模型 */ socket(); bind(); listen(); while(true) 
{ accept(); while(true) { recv(); process(); send(); } close(); 
}
復制代碼

從上面的的流程可以看出,TCP循環服務器比UDP循環服務器多了一個accept的過程,這也是TCP和UDP套接字編程的主要區別。TCP服務器在accept出等待客戶端的到來,因為accept函數是阻塞的,因此TCP服務器會在此等待(對accept函數的不同處理是區分各類服務器的一個重要參考依據)。相應地,UDP會在recvfrom阻塞,并等待客戶端的連接。

一個循環服務器的例子

下面給出一個簡單的循環服務器樣子,模擬服務器對外提供時間服務器,等待客戶端到來,并返回給客戶端服務器的當前時間。

UDP循環服務器

復制代碼
 1 /** UDP循環服務器--server端程序**/
 2 #include <sys/types.h>
 3 #include <sys/socket.h>
 4 #include <netinet/in.h>
 5 #include <time.h>
 6 #include <string.h>
 7 #include <stdio.h>
 8 #define BUFFLEN 1024
 9 #define SERVER_PORT 12345
10 int main(int argc, char *argv[])
11 {
12     int s;    //服務器套接字文件描述符
13     struct sockaddr_in local, to;    //本地地址
14     time_t now;        //時間
15     char buff[BUFFLEN];//收發數據緩沖區
16     int n = 0;
17     int len = sizeof(to);
18     
19     //建立UDP套接字
20     s = socket(AF_INET, SOCK_DGRAM, 0);
21     
22     //初始化地址
23     memset(&local, 0, sizeof(local));
24     local.sin_family = AF_INET;//AF_INET協議族
25     local.sin_addr.s_addr = htonl(INADDR_ANY);//任意本地地址
26     local.sin_port = htons(SERVER_PORT);//服務器端口
27     
28     //將套接字文件描述符綁定到本地地址和端口
29     int err = bind(s, (struct sockaddr*)&local, sizeof(local));
30     
31     //主處理過程
32     while(1)
33     {
34         memset(buff, 0, BUFFLEN);
35         n = recvfrom(s, buff, BUFFLEN,0,(struct sockaddr*)&to, &len);//接收發送方數據
36         if(n > 0 && !strncmp(buff, "TIME", 4))//判斷是否合法接收數據
37         {
38             printf("Get One Client Connect\n");
39             memset(buff, 0, BUFFLEN);
40             now = time(NULL);
41             sprintf(buff, "%24s\r\n",ctime(&now));
42             sendto(s, buff, strlen(buff),0, (struct sockaddr*)&to, len);//發送數據
43         }
44     }
45     close(s);
46     
47     return 0;        
48 }
復制代碼
復制代碼
 1 /** UDP循環服務器--client端程序**/
 2 #include <sys/types.h>
 3 #include <sys/socket.h>
 4 #include <netinet/in.h>
 5 #include <time.h>
 6 #include <string.h>
 7 #include <stdio.h>
 8 #define BUFFLEN 1024
 9 #define SERVER_PORT 12345
10 int main(int argc, char *argv[])
11 {
12     int s;    //服務器套接字文件描述符
13     struct sockaddr_in server;    //本地地址
14     time_t now;         
15     char buff[BUFFLEN]; 
16     int n = 0;     
17     int len = 0;    //地址長度
18     
19     //建立UDP套接字
20     s = socket(AF_INET, SOCK_DGRAM, 0);
21     
22     //初始化地址接 
23     memset(&server, 0, sizeof(server));
24     server.sin_family = AF_INET;//AF_INET協議族
25     server.sin_addr.s_addr = htonl(INADDR_ANY);//任意本地地址
26     server.sin_port = htons(SERVER_PORT);//服務器端口
27     
28     memset(buff, 0, BUFFLEN); 
29     strcpy(buff, "TIME"); 
30     //發送數據
31     sendto(s, buff, strlen(buff), 0, (struct sockaddr*)&server, sizeof(server));
32     memset(buff, 0, BUFFLEN);
33     //接收數據
34     len = sizeof(server);
35     n = recvfrom(s, buff, BUFFLEN, 0, (struct sockaddr*)&server, &len);
36     if(n >0)
37         printf("TIME:%s",buff);    
38     
39     close(s);
40     
41     return 0;        
42 }
復制代碼

  

TCP循環服務器

復制代碼
 1 /** TCP循環服務器--server端程序**/
 2 #include <sys/types.h>
 3 #include <sys/socket.h>
 4 #include <netinet/in.h>
 5 #include <time.h>
 6 #include <string.h>
 7 #include <stdio.h>
 8 #define BUFFLEN 1024
 9 #define SERVER_PORT 12346
10 #define BACKLOG 5
11 int main(int argc, char *argv[])
12 {
13     int s_s, s_c;    /*服務器套接字文件描述符*/
14     struct sockaddr_in local, from;    /*本地地址*/
15     time_t now;        
16     char buff[BUFFLEN];
17     int n = 0;
18     int len = sizeof(from);
19     
20     /*建立TCP套接字*/
21     s_s = socket(AF_INET, SOCK_STREAM, 0);
22     
23     /*初始化地址*/
24     memset(&local, 0, sizeof(local));
25     local.sin_family = AF_INET;/*AF_INET協議族*/
26     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
27     local.sin_port = htons(SERVER_PORT);/*服務器端口*/
28     
29     /*將套接字文件描述符綁定到本地地址和端口*/
30     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
31     err = listen(s_s, BACKLOG);/*偵聽*/
32     
33     /*主處理過程*/
34     while(1)
35     {
36         /*接收客戶端連接*/
37         s_c = accept(s_s, (struct sockaddr*)&from, &len);
38         memset(buff, 0, BUFFLEN);
39         n = recv(s_c, buff, BUFFLEN,0);/*接收發送方數據*/
40         if(n > 0 && !strncmp(buff, "TIME", 4))/*判斷是否合法接收數據*/
41         {
42             memset(buff, 0, BUFFLEN);
43             now = time(NULL);
44             sprintf(buff, "%24s\r\n",ctime(&now));
45             send(s_c, buff, strlen(buff),0);/*發送數據*/
46         }
47         close(s_c);
48     }
49     close(s_s);
50     
51     return 0;        
52 }
復制代碼
 
復制代碼
/**TCP循環服務器--client端程序**/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>#define BUFFLEN 1024
#define SERVER_PORT 12346
int main(int argc, char *argv[])
{int s;    /*服務器套接字文件描述符*/struct sockaddr_in server;    /*本地地址*/char buff[BUFFLEN];int n = 0;    /*建立TCP套接字*/s = socket(AF_INET, SOCK_STREAM, 0);/*初始化地址*/memset(&server, 0, sizeof(server));server.sin_family = AF_INET;/*AF_INET協議族*/server.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/server.sin_port = htons(SERVER_PORT);/*服務器端口*/    /*連接服務器*/int err = connect(s, (struct sockaddr*)&server,sizeof(server));memset(buff, 0, BUFFLEN);strcpy(buff, "TIME");/*發送數據*/send(s, buff, strlen(buff), 0);memset(buff, 0, BUFFLEN);/*接收數據*/    n = recv(s, buff, BUFFLEN, 0);if(n >0){printf("TIME:%s",buff);    }close(s);return 0;        
}
復制代碼

?

兩者返回給客戶端的的輸出都是一樣的,比如:TIME:Sat Mar 22 15:26:25 2014

?

循環服務器的介紹就到這里。接下來介紹并發服務器模型。



本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384327.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384327.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384327.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

劍指Offer04. 二維數組中的查找

在一個 n * m 的二維數組中&#xff0c;每一行都按照從左到右遞增的順序排序&#xff0c;每一列都按照從上到下遞增的順序排序。請完成一個高效的函數&#xff0c;輸入這樣的一個二維數組和一個整數&#xff0c;判斷數組中是否含有該整數。 相當于二叉搜索樹,左孩子比根節點小&…

Linux網絡編程服務器模型選擇之并發服務器(上)

轉載&#xff1a;http://www.cnblogs.com/lizhenghn/p/3617666.html 與循環服務器的串行處理不同&#xff0c;并發服務器對服務請求并發處理。循環服務器只能夠一個一個的處理客戶端的請求&#xff0c;顯然效率很低。并發服務器通過建立多個子進程來實現對請求的并發處理。并發…

劍指Offer10- II. 青蛙跳臺階問題

一只青蛙一次可以跳上1級臺階&#xff0c;也可以跳上2級臺階。求該青蛙跳上一個 n 級的臺階總共有多少種跳法。 答案需要取模 1e97&#xff08;1000000007&#xff09;&#xff0c;如計算初始結果為&#xff1a;1000000008&#xff0c;請返回 1。 示例 1&#xff1a; 輸入&a…

Linux網絡編程服務器模型選擇之并發服務器(下)

轉載&#xff1a;http://www.cnblogs.com/lizhenghn/p/3618986.html 前面兩篇文章&#xff08;參見&#xff09;分別介紹了循環服務器和簡單的并發服務器網絡模型&#xff0c;我們已經知道循環服務器模型效率較低&#xff0c;同一時刻只能為一個客戶端提供服務&#xff0c;而且…

劍指Offer05. 替換空格

請實現一個函數&#xff0c;把字符串 s 中的每個空格替換成"%20"。 示例 1&#xff1a; 輸入&#xff1a;s “We are happy.” 輸出&#xff1a;“We%20are%20happy.” class Solution { public:string replaceSpace(string s) {int count0;int lens.size();stri…

Linux網絡編程服務器模型選擇之IO復用循環并發服務器

轉載&#xff1a;http://www.cnblogs.com/lizhenghn/p/3619091.html 在前面我們介紹了循環服務器&#xff0c;并發服務器模型。簡單的循環服務器每次只能處理一個請求&#xff0c;即處理的請求是串行的&#xff0c;效率過低&#xff1b;并發服務器可以通過創建多個進程或者是線…

數據結構(六)二叉樹的遍歷(遞歸非遞歸方法)

數據結構&#xff08;六&#xff09;二叉樹的遍歷&#xff08;遞歸非遞歸方法&#xff09; 一、遞歸方法 1.先序遍歷 void PreOrder(BiTree T) {visit(T);PreOrder(T->LChild)PreOrder(T->RChild) }2.先序遍歷 void PreOrder(BiTree T) {PreOrder(T->LChild)visit…

memcpy/memset函數的c語言實現

轉載&#xff1a;http://blog.csdn.net/u011118276/article/details/46742341 1、memcpy 頭文件&#xff1a;#include <string.h> 函數原型&#xff1a;void *memcpy(void *dest, const void *src, size_t n) 功能&#xff1a;將指針src指向的內存空間的n個字節復制到des…

計算機網絡(一)計算機網絡體系

計算機網絡&#xff08;一&#xff09;計算機網絡體系一、計算機網絡概述概念功能組成分類二、體系結構和參考模型ISO/OSI模型物理層網絡層傳輸層會話層表示層應用層OSI參考模型與TCP/IP參考模型OSI參考模型與TCP/IP參考模型不同5層參考模型一、計算機網絡概述 概念 計算機網…

計算機網絡(二)物理層

計算機網絡&#xff08;二&#xff09;物理層一、通信基礎物理層接口特性1.機械特性2.電氣特性3.功能特性4.規程特性典型的數據通信模型三種通信方式1.單工通信2.半雙工通信/雙向交替通信3.全雙工通信/雙向同時通信數據傳輸方式串行傳輸并行傳輸同步傳輸異步傳輸二、數據交換方…

計算機網絡(三)數據鏈路層

計算機網絡&#xff08;三&#xff09;數據鏈路層1.基本概念2.功能概述3.組幀字符計數法字符填充法零比特填充法違規編碼法4.差錯控制檢錯編碼奇偶校驗碼CRC循環冗余碼糾錯編碼海明碼流量控制停止等待協議滑動窗口協議后退N幀協議&#xff08;GBN&#xff09;選擇重傳協議5.介質…

libevent網絡編程例子(1)

轉載&#xff1a;http://blog.csdn.net/huangyimo/article/details/46806193 這篇文章介紹下libevent在socket異步編程中的應用。在一些對性能要求較高的網絡應用程序中&#xff0c;為了防止程序阻塞在socket I/O操作上造成程序性能的下降&#xff0c;需要使用異步編程&#xf…

計算機網絡(四)網絡層

計算機網絡&#xff08;四&#xff09;網絡層一、概述和功能TCP/IP協議棧IP數據報格式IP數據報分片二、ipv4網絡地址轉換&#xff08;NAT&#xff09;子網劃分子網掩碼ARP協議&#xff08;地址解析協議&#xff09;DHCP協議ICMP協議二、ipv6ipv4和ipv6的區別IPv6基本地址類型IP…

Linux下基于socket和多線程的聊天室小程序

轉載&#xff1a;http://blog.csdn.net/robot__man/article/details/52460733 要求&#xff1a;基于TCP編寫&#xff0c;一個聊天室最多100人。 客戶端&#xff1a;   1、用戶需要登錄&#xff0c;登錄時只需要輸入一個昵稱即可無需判斷昵稱是否重復&#xff08;如果其他功…

操作系統(一)計算機系統概述

操作系統&#xff08;一&#xff09;計算機系統概述一、操作系統的概念二、功能和目標資源的管理者向上層提供服務對硬件的擴展三、操作系統的特征并發共享虛擬異步四、操作系統的發展與分類手工操作階段批處理階段單道批處理系統多道批處理系統分時操作系統實時操作系統操作系…

Linux下使用socket傳輸文件的C語言簡單實現

轉載&#xff1a;http://blog.csdn.net/ljd_1986413/article/details/7940938 服務器程序和客戶端程序應當分別運行在兩臺計算機上。 在運行服務器端的計算機終端執行&#xff1a;./file_server 在運行客戶端的計算終端上執行&#xff1a;./file_client ipaddr_server 然后根…

操作系統(二)進程管理

ui 操作系統&#xff08;二&#xff09;進程管理一、進程程序和進程進程控制塊&#xff08;PCB&#xff09;進程的組成進程的特征進程的狀態與轉換進程狀態的轉換進程的組織鏈接方式索引方式進程的控制進程的創建進程的終止進程阻塞進程喚醒進程切換進程通信共享存儲消息傳遞管…

gethostbyname()函數說明

轉載&#xff1a;http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881611.html gethostbyname()函數說明——用域名或主機名獲取IP地址 包含頭文件 #include <netdb.h> #include <sys/socket.h> 函數原型 struct hostent *gethostbyna…

操作系統(三)內存管理

操作系統&#xff08;三&#xff09;內存管理一、程序執行過程裝入的三種方式鏈接的三種方式二、內存管理的概念內存空間的分配與回收連續分配管理方式單一連續分配固定分區分配動態分區分配首次適應算法最佳適應算法最壞適應算法鄰近適應算法非連續分配管理方式基本分頁存儲管…

操作系統(四)文件管理

操作系統&#xff08;四&#xff09;文件管理一、文件系統基礎1.文件邏輯結構無結構文件有結構文件2.文件目錄文件控制塊&#xff08;FCB&#xff09;目錄結構單級目錄兩級目錄結構多級目錄結構無環圖目錄結構3.文件保護口令保護加密保護訪問控制4.文件共享硬鏈接軟鏈接5.文件系…