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

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

? 與循環服務器的串行處理不同,并發服務器對服務請求并發處理。循環服務器只能夠一個一個的處理客戶端的請求,顯然效率很低。并發服務器通過建立多個子進程來實現對請求的并發處理。并發服務器的一個難點是如何確定子進程的數據,因為不清楚請求客戶端的數目,因此實現中通常采用事先分配一定數目的子進程與動態增加子進程相結合的方法來實現并發服務器。

簡單并發服務器模型

復制代碼
/* UDP簡單并發服務器模型 */
/* 服務器主進程 */
socket(...);
bind(...);
fork(); //創建多個子進程進行請求處理
while(1);
/* 服務器子進程1 */
while(1)
{recvfrom(....);process(...);sendto(.....);
}
close(...); 
/* 服務器子進程2(同上) */
..................
..................
..................
/* 服務器子進程3(同上) */
..................
..................
..................
復制代碼
復制代碼
/* TCP簡單并發服務器模型 */
/* 服務器主進程 */
socket(...);
bind(...);
fork();//創建多個子進程進行請求處理
while(1);
/* 服務器子進程1 */
socket(...);
bind(...);
listen(...);
while(1)
{accept(...);recv(....)process(...);send(.....);
}
close(....);
/* 服務器子進程2(同上) */
..................
..................
..................
/* 服務器子進程3(同上) */
..................
..................
..................
復制代碼

?

一個并發服務器的例子

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

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 12347
10 #define BACKLOG 5
11 
12 static void handle_request(int s, struct sockaddr_in* from, char *buff)
13 {
14     time_t now;        
15     int len = sizeof(*from);
16     memset(buff, 0, BUFFLEN);
17     now = time(NULL);
18     sprintf(buff, "%24s\r\n",ctime(&now));
19     sendto(s, buff, strlen(buff),0, (struct sockaddr*)from, len);/*發送數據*/
20 }
21 
22 static void handle_connect(int s_s)
23 {    
24     struct sockaddr_in from;    /*客戶端地址*/
25     int len = sizeof(from);
26     int n = 0;
27     char buff[BUFFLEN];
28 
29     /*主處理過程*/
30     while(1)
31     {
32         memset(buff, 0, BUFFLEN);
33         /*接收客戶端連接*/
34         n = recvfrom(s_s, buff, BUFFLEN,0,(struct sockaddr*)&from, &len);/*接收發送方數據*/
35         if(n > 0 && !strncmp(buff, "TIME", 4))/*判斷是否合法接收數據*/
36         {
37             /*創建進程進行數據處理*/
38             if(!fork())
39             {
40                 handle_request(s_s, &from, buff);/*處理連接請求*/
41                 return ;    
42             }
43         }
44     }        
45 }
46 
47 
48 int main(int argc, char *argv[])
49 {
50     int s_s;    /*服務器套接字文件描述符*/
51     struct sockaddr_in local;    /*本地地址*/    
52     
53     /*建立TCP套接字*/
54     s_s = socket(AF_INET, SOCK_STREAM, 0);
55     
56     /*初始化地址接哦股*/
57     memset(&local, 0, sizeof(local));
58     local.sin_family = AF_INET;/*AF_INET協議族*/
59     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
60     local.sin_port = htons(SERVER_PORT);/*服務器端口*/
61     
62     /*將套接字文件描述符綁定到本地地址和端口*/
63     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
64         
65     /*處理客戶端連接*/
66     handle_connect(s_s);
67     
68     close(s_s);
69     
70     return 0;        
71 }
復制代碼

?

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 12347
10 #define BACKLOG 5
11 
12 static void handle_request(int s_c)
13 {
14     time_t now;        
15     char buff[BUFFLEN];
16     int n = 0;
17     memset(buff, 0, BUFFLEN);
18     n = recv(s_c, buff, BUFFLEN,0);/*接收發送方數據*/
19     if(n > 0 && !strncmp(buff, "TIME", 4))/*判斷是否合法接收數據*/
20     {
21         memset(buff, 0, BUFFLEN);
22         now = time(NULL);
23         sprintf(buff, "%24s\r\n",ctime(&now));
24         send(s_c, buff, strlen(buff),0);/*發送數據*/
25     }        
26     /*關閉客戶端*/
27     close(s_c);    
28 }
29 
30 static void handle_connect(int s_s)
31 {    
32     int s_c;    /*客戶端套接字文件描述符*/
33     struct sockaddr_in from;    /*客戶端地址*/
34     int len = sizeof(from);
35     
36     /*主處理過程*/
37     while(1)
38     {
39         /*接收客戶端連接*/
40         s_c = accept(s_s, (struct sockaddr*)&from, &len);
41         if(s_c > 0)/*客戶端成功連接*/
42         {
43             /*創建進程進行數據處理*/
44             if(fork() > 0)/*父進程*/
45             {
46                 close(s_c);/*關閉父進程的客戶端連接套接字*/
47             }
48             else
49             {
50                 handle_request(s_c);/*處理連接請求*/
51                 return ;    
52             }
53         }
54     }        
55 }
56 
57 
58 int main(int argc, char *argv[])
59 {
60     int s_s;    /*服務器套接字文件描述符*/
61     struct sockaddr_in local;    /*本地地址*/    
62     
63     /*建立TCP套接字*/
64     s_s = socket(AF_INET, SOCK_STREAM, 0);
65     
66     /*初始化地址*/
67     memset(&local, 0, sizeof(local));
68     local.sin_family = AF_INET;/*AF_INET協議族*/
69     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
70     local.sin_port = htons(SERVER_PORT);/*服務器端口*/
71     
72     /*將套接字文件描述符綁定到本地地址和端口*/
73     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
74     err = listen(s_s, BACKLOG);/*偵聽*/
75     
76     /*處理客戶端連接*/
77     handle_connect(s_s);
78     
79     close(s_s);
80     
81     return 0;        
82 }
復制代碼

?

注意,

1. 為了方便退出,server程序中對信號SIGINT信號進行了處理,此時所有的進程都會退出;

2. 并發服務器中的client程序與上一節介紹循環服務器時使用的client程序是一樣的,這里不在貼出來,

? ? 請參考?Linux網絡編程服務器模型選擇之循環服務器?http://www.cnblogs.com/lizhenghn/p/3617608.html


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

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

相關文章

劍指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.文件系…

struct stat結構體簡介

轉載&#xff1a;http://www.cnblogs.com/CSU-PL/archive/2013/06/06/3120757.html 在使用這個結構體和方法時&#xff0c;需要引入&#xff1a; <sys/types.h> <sys/stat.h> struct stat這個結構體是用來描述一個linux系統文件系統中的文件屬性的結構。 可以有兩種…

如何在Ubuntu上安裝GCC編譯器

如何在Ubuntu上安裝GCC編譯器1.首先更新包列表sudo apt update2.安裝build-essential軟件包&#xff1a; sudo apt install build-essential3.驗證GCC編譯器是否已成功安裝&#xff0c;請使用gcc --version命令打印GCC版本 rootubuntu:/home/csd# gcc --version