回射客戶 伺服器模型(1)

2021-07-27 09:55:26 字數 3126 閱讀 4048

最近在學習socket程式設計,根據自己的學習過程及學習筆記,下面來梳理一下如何實現乙個簡單的回射客戶-伺服器模型,也藉此來熟悉一下socket、bind、listen、accept、connect這些函式的使用。

簡單的回射客戶/伺服器模型

下面先看一下乙個客戶/伺服器模型的框架圖。

可以看到,伺服器建立過程一般是:

1)建立套接字,使用socket函式,這個時候的套接字是主動套接字

2)初始化伺服器端位址,並使用bind函式將套介面與該位址進行繫結;

3)監聽,使用listen函式,將套介面從close狀態轉為監聽狀態才能夠接收客戶端發起的連線,同時經過監聽之後,伺服器端的套接字從主動狀態(發起連線)變為被動狀態(接收連線);

4)等待接收連線,accept函式,使用該函式後,伺服器端一直處於阻塞狀態,直到客戶端的連線到達;

5)等客戶端的連線到達後,雙方開始進行通訊(讀寫資料);

客戶端建立的過程就相對簡單了:

1)建立套接字;

2)使用connect函式發起連線(過程中要經過三次握手);

3)連線成功,雙方相互進行通訊;

下面以**的方式具體說明每一步驟的實現。

伺服器端

// 1. 建立套接字

int listenfd;

if((listenfd = socket(af_inet, sock_stream, 0)) < 0)

perror("socket create error");

// 2. 初始化位址

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr));

servaddr.sin_family = af_inet;//位址族

servaddr.sin_port = htons(5188); //埠

servaddr.sin_addr.s_addr = htonl(inaddr_any);// 表示本機的任意位址,當然也可以自己指定

= inet_addr("127.0.0.1");

// 3. 繫結bind

if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

perror("bind error");

// 4. 監聽listen

if(listen(listenfd, somaxconn) < 0)//第二個引數表示每乙個埠的最大監聽佇列長度

perror("listen error");

// 5. 接收連線

// 在接收連線前,先定義乙個位址結構,用來儲存對等方的位址

struct sockaddr_in peeraddr;

socklen_t peerlen = sizeof(peeraddr);

memset(&peeraddr, 0, peerlen);

int conn;

// 成功返回對等方的套介面

if((conn = accept(lisenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0)

perror("accept error");

//輸出客戶端的位址和埠(僅測試用)

printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));

// 至此,雙方連線已完成,可以進行通訊

char recvbuf[1024];

while(1)

//關閉套介面

close(lisenfd);

close(conn);

需要對上述的一些步驟做一些說明:

1)在初始化位址的時候,伺服器端位址可以指定為具體某一ip,也可以是inaddr_any。這裡建議選用inaddr_any引數,表示位址0.0.0.0,也就是不確定的位址,或「所有位址」、「任意位址」。如果你的伺服器有多個網絡卡,你要在5188這個埠上監聽,所有傳送到伺服器的這個埠,不管是哪個網絡卡/哪個ip位址接收到的資料,都可以進行處理。

2)關於listen函式中的第二個引數。每乙個處於監聽狀態的埠,都要自己的監聽佇列,那麼該引數就指定了監聽佇列的長度。我們可以自己指定乙個正整數,也可以使用引數somanconn,它表示每個埠的最大監聽佇列長度。

客戶端:

// 1. 建立套接字

int sock;

if((sock = socket(af_inet, sock_stream, 0)) < 0)

perror("socket create error");

// 2. 初始化乙個你要連線的對方的位址

struct sockaddr_in servaddr;

memset(&servaddr, 0, sizeof(servaddr);

servaddr.sin_family = af_inet;

servaddr.sin_port = htons(5188);

servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");

// 3. 發起連線

if(connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)

perror("connect error");

// 4. 進行通訊(讀寫資料)

char recvbuf[1024] = ;

char sendbuf[1024] = ;

while(fgets(sendbuf, sizeof(sendbuf), stdin) != null)

//關閉套介面

close(sock);

用select改進回射客戶 伺服器模型

這一節主要來說一下如何用select函式來改進我們前面的客戶端 伺服器模型。前面我們在處理多客戶端模型時,每當連線乙個客戶端時,伺服器端就需要開闢乙個新的程序來處理新的客戶端,這樣就會耗費很大的記憶體資源。而select函式允許程序指示核心等待多個事件中的任何乙個發生,並只有在有乙個或多個事件事件發...

TCP 回射伺服器

tcp reflect server client tcp回射伺服器。學習了 unp 的第五章前面的知識,自己把 敲出來了,加深了理解吧。簡單地說就是,client傳送給server一條訊息 一行文字 server再將同樣地訊息傳送回client。就像這樣 用到的函式和api包括 1 socket ...

Linux C 回射伺服器

回射伺服器就是服務端將客戶端的資料傳送回去。我實現的回射伺服器返回增加了時間。服務端 可以很容易看懂 cpp view plain copy include include include include include include include include include define ...