socke通訊之三 阻塞版本的客戶 伺服器模型

2021-08-21 03:45:08 字數 3634 閱讀 5158

socke通訊之三:阻塞版本的客戶/伺服器模型

乙個很直觀地想法就是修改客戶端的第4步,即傳送,接收資料那一步,在基本的客戶/伺服器模型中我們是直接傳送乙個字串給伺服器端,現在我們從控制台接收資料將接收到的資料傳送給伺服器端,然後從服務端端接收資料並列印輸出。並持續從控制台讀取資料。

而伺服器端也只需要更改第6步,即呼叫send和recv這兩個函式和客戶端進行通訊這一步,在源**中通過注釋可以很方便找到這一步,現在伺服器端也需要持續從客戶端接收資料,將接收到的資料顯示在客戶端,然後在這個資料前面加上「message from client:」這個字串後再將字串傳送給客戶端。

可以發現,客戶端的**只在第4步進行了修改,而伺服器端的**只在第6步進行了修改。

伺服器端的**:

[cpp]view plain

copy

#include 

#include 

#include 

#include 

#pragma comment(lib, "ws2_32.lib")

using

namespace std;  

#define  port 6000

//#define  ip_address "10.11.163.113"

#define  ip_address "127.0.0.1" //設定連線的伺服器的ip位址

void main()  

//2.建立socket

//套接字描述符,socket實際上是unsigned int

socket serversocket;  

serversocket=socket(af_inet,sock_stream,0);  

if (serversocket==invalid_socket)  

//伺服器端的位址和埠號

struct sockaddr_in serveraddr,clientadd;  

serveraddr.sin_addr.s_addr=inet_addr(ip_address);  

serveraddr.sin_family=af_inet;  

serveraddr.sin_port=htons(port);  

//3.繫結socket,將socket與某個協議的某個位址繫結

err=bind(serversocket,(struct sockaddr*)&serveraddr,sizeof(serveraddr));  

if (err!=0)  

//4.監聽,將套接字由預設的主動套接字轉換成被動套接字

err=listen(serversocket,10);  

if (err!=0)  

cout<

<

int addrlen=sizeof(clientadd);  

while(true)  

cout<

<

char recebuff[max_path];  

char sendbuf[max_path];  

//6.呼叫send和recv這兩個函式和客戶端進行通訊,相比於第乙個版本,只有這一步發生了變化

while(true)  

cout<

strcat(sendbuf,recebuff);  

//傳送資料

send(sockconn,sendbuf,strlen(sendbuf)+1,0);       

}  //關閉這個socket

closesocket(sockconn);  

}  closesocket(serversocket);  

//清理windows socket庫

wsacleanup();  

}  

客戶端**:

[cpp]view plain

copy

#include 

#include 

#include 

#include 

#pragma comment(lib, "ws2_32.lib")

#define  port 6000

//#define  ip_address "10.11.163.113"  //表示伺服器端的位址

#define  ip_address "127.0.0.1"  //直接使用本機位址

using

namespace std;  

void main()  

//2.建立socket

socket sockclient=socket(af_inet,sock_stream,0);  

struct sockaddr_in addrserver;  

addrserver.sin_addr.s_addr=inet_addr(ip_address);  

addrserver.sin_family=af_inet;  

addrserver.sin_port=htons(port);  

//3.連線socket,第乙個引數為客戶端socket,第二個引數為伺服器端位址

err=connect(sockclient,(struct sockaddr *)&addrserver,sizeof(addrserver));  

if (err!=0)  

else

char sendbuff[max_path];  

char recvbuf[max_path];  

while (true)  

//4.關閉套接字

closesocket(sockclient);  

wsacleanup();  

}  

上面這個模型在只有乙個客戶端時是能正常執行的,如下:

客戶端連線伺服器成功後會在客戶端顯示「連線成功!」的字串,同時伺服器端也顯示連線成功的客戶端的ip位址和埠號,接著客戶端傳送hello,nihao,good給伺服器端,伺服器每次收到乙個字串會在伺服器端顯示"message from client:"+字串。

乙個客戶端連線時伺服器端能正常工作,但是有多個客戶端連線時伺服器端就會出問題了,這是由於預設情況下socket是阻塞式的,在上面伺服器端的**中第6步現在被替換成了乙個迴圈來連續接受來自哪個連線的資料,在這個連線沒有斷開之前,它是不會再次進行accept呼叫,連線其它客戶端的。

如下圖所示:當再次啟動乙個客戶端時,客戶端顯示「連線成功!」表示客戶端的connect成功返回,但是伺服器端沒有顯示「客戶端連線:」這行字串,這行字串是在accept函式返回時呼叫的,所以accept函式此時沒有返回。原因也很簡單,伺服器陷入第6步接收資料和傳送資料中的死迴圈了。

當關閉第乙個客戶端以後,伺服器端會可以變成下圖所示:顯示有客戶端退出,並顯示有客戶端連線。

socke通訊之三:阻塞版本的客戶/伺服器模型

伺服器和客戶端的通訊

伺服器 include include include include include include include include define port 8888 int main struct sockaddr in server addr 用於存放伺服器本身的資訊,包括自己的port和ip...

客戶端與伺服器之間的通訊

今天我們來 一下通訊群聊的實現,就像平常我們玩的qq群聊功能一樣,有多個賬號發訊息能互相接收到,其實這個資料傳輸的過程是在客戶端和伺服器間實現的。所以我們要先建立乙個伺服器端口。public class chatserver在資料傳輸之前,客戶端和伺服器有三次握手。1.客戶端告訴伺服器自己要建立連線...

Qt E伺服器客戶端的通訊機制

qt e 伺服器和客戶端的通訊機制和 x11協議一樣都是通過 unix 域socket 來進行通訊的,只不過兩者之間具體的協議並不一樣,qt e 使用的協議相對比較簡單。伺服器到客戶端的協議格式是 qwsevent 客戶端到伺服器的協議格式是 qwscommand qt e中的伺服器客戶端通訊協議是...