linux回聲伺服器系列 2 select實現

2021-10-23 03:20:43 字數 3394 閱讀 4688

在網路程式設計中,回聲伺服器(echo server)是乙個典型的例子。

實現非併發伺服器很容易,即迭代伺服器;

實現併發伺服器需要採用io復用或併發程式設計技術。

在這個系列中將分別採用簡易迭代、select函式、epoll函式(水平觸發和邊沿觸發)、多程序、多執行緒五種方式來實現回聲伺服器。

傳送門:

linux回聲伺服器系列(1)_簡單迭代版本

linux回聲伺服器系列(2)_select實現

linux回聲伺服器系列(3)_epoll實現

linux回聲伺服器系列(4)_多程序版本

linux回聲伺服器系列(5)_多執行緒併發

採用select函式能實現基本的io多路復用,實現伺服器為多個客戶端提供服務的功能。

客戶端將使用者輸入的字串傳送到伺服器,伺服器收到後原封不動傳送回客戶端,實現回聲。

客戶端輸入字元q後退出。

伺服器監聽乙個監聽描述符listenfd,來獲取新的客戶端連線。此外,還維護乙個client陣列,儲存每個已連線客戶端的套接字描述,如下圖。

主函式**,select的具體處理步驟在select_server函式中。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

constexpr

int port =

2345

;constexpr

int bufmaxlen =

128;

int client[fd_setsize]

;int

main

(int argc,

char

* ar**)

;char recvbuf[bufmaxlen]=;

struct sockaddr_in server_addr, client_addr;if(

(sockfd =

socket

(af_inet, sock_stream,0)

)==-1

)memset

(&server_addr,0,

sizeof

(struct sockaddr_in));

server_addr.sin_family = af_inet;

server_addr.sin_port =

htons

(port)

; server_addr.sin_addr.s_addr =

htonl

(inaddr_any);if

(bind

(sockfd,

(struct sockaddr*)(

&server_addr)

,sizeof

(struct sockaddr))==

-1)if

(listen

(sockfd, somaxconn)==-

1)std::cout<<

"server start... "

<<:endl>

select_server

(sockfd)

;close

(sockfd)

;return0;

}

select函式返回時可能有兩種情況:

監聽描述符可讀,有了新的客戶端連線,則accept建立連線,獲取客戶端套接字描述符,存入client陣列中。

client中的套接字描述符有可讀事件,則遍歷client陣列做相應處理。

select_server函式的具體實現:

void

select_server

(int listenfd)

/*select返回可能有兩種情況*/

/*1.監聽描述符可讀,有了新連線*/if(

fd_isset

(listenfd,

&fdset)

)/*找到client中的空位子填進去*/

for(i =

0; i < fd_setsize; i++)}

if(i == fd_setsize)

std::cout<<

"accept client ip: "

<<

inet_ntoa

(client_addr.sin_addr)

<<

" on socket: "

<

/*更新索引資訊和核心描述符集*/

max_client_index =

(i > max_client_index)

? i : max_client_index;

fd_set

(connfd,

&allset)

; maxfd =

(connfd > maxfd)

? connfd : maxfd;

}/*2.client中的套接字描述符有可讀事件*/

for(i =

0; i <= max_client_index; i++

)else

//回寫

write

(client[i]

, recv_buf, recv_bytes);}}}}

客戶端**見linux回聲伺服器系列(1)_簡單版本

伺服器

客戶端1

客戶端2

可以看到,服務端能同時處理多個客戶端的請求。

有最大監聽描述符個數的限制。

呼叫select每次都需要向核心拷貝整個描述符集資訊。

select返回後並不會告訴你哪些描述符準備好了,需要自行遍歷檢查。

這些缺點可以通過epoll進行一定程度上的彌補,見下篇。

與epoll相比,select並非毫無優點。

在監聽描述符個數較少,且都較活躍的情況下,由於select的實現更簡易,效率會比epoll更高。

select的優點還體現在其良好的相容性,在幾乎所有作業系統下都能使用。

epoll回聲伺服器

epoll是在linux系統中,一種高效率的i o復用技術.在linux的網路程式設計中,很長的時間都在使用select來做事件觸發。在linux新的核心中,有了一種替換它的機制,就是epoll。相比於select,epoll最大的好處在於它不會隨著監聽fd數目的增長而降低效率。因為在核心中的sel...

基於TCP IP的回聲伺服器 Linux環境

注意 需要聯網 需要修改ip位址為自己的ip位址。ifconfig檢視自己的ip位址 include include include include include include include include define buf size 4096 void server void arg p...

C 回聲伺服器 2 修復客戶端問題

c 回聲伺服器 1 簡單版本中的問題出在客戶端。客戶端通過write函式一次性傳送資料,過一段時間再呼叫一次read函式,期望接收傳輸的資料。問題在於這段時間到底是多久?理想的客戶端應在接收到資料時立即讀取資料。客戶端傳送資料時,可以知道資料的大小 長度 客戶端接收資料的時候,可以知道接收到資料的大...