在網路程式設計中,回聲伺服器(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函式,期望接收傳輸的資料。問題在於這段時間到底是多久?理想的客戶端應在接收到資料時立即讀取資料。客戶端傳送資料時,可以知道資料的大小 長度 客戶端接收資料的時候,可以知道接收到資料的大...