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中的伺服器客戶端通訊協議是...