基於TCP協議的伺服器 客戶端程式

2021-04-23 20:47:27 字數 3042 閱讀 1915

前面我們初步學習了資料流套接字程式設計的一些基礎知識,下面我們來學習如何具體實現這一網路通訊流程。首先我們看一下使用tcp協議進行網路通訊的程式基本模型,如圖7-3所示。

伺服器首先進行初始化操作:呼叫函式socket建立乙個套接字,函式bind將這個套接字與伺服器的公認位址繫結在一起,函式listen將這個套接字 換成傾聽套接字,然後呼叫函式accept來等待客戶機的請求。過了一段時間後,客戶機啟動,呼叫socket建立乙個套接字,然後呼叫函式 connect來與伺服器建立連線。連線建立之後,客戶機和伺服器通過讀、寫套接字來進行通訊。

熟練使用上圖所示的所有函式是編寫網路程式的重要前提,下面我們就挑選幾個重要的函式進行講解,其它的可以參考linux的幫助手冊。

socket()函式原型為:

#include

#include

int socket(int domain,int type,int protocol);

引數domain指定要建立的套接字的協議簇,具體見表7-1;引數type指定套接字型別,具體見表7-2;引數protocol指定使用哪種協議。函式socket成功執行時,返回乙個正整數,稱為套接字描述符,否則返回-1,並設定errno為相應的錯誤型別。

表7-1 domain的取值及其含義

flags

含義

af_unix

unix協議簇,本機的程序通訊時使用

af_inet

internet協議簇(tcp/ip)

af_iso

iso協議簇

表7-2 type的取值及其含義

flags

含義

sock_stream

流式套接字

af_dgram

資料報套接字

af_raw

原始套接字

bind()函式原型為:

#include

#include

int bind(int sockfd,struct sockaddr *my_addr,int addrlen);

sockfd是呼叫socket返回的檔案描述符;my_addr儲存位址資訊(埠和ip位址);addrlen設定為套接字位址的長度,即sizeof(struct sockaddr)。函式bind成功執行時返回0;否則返回-1,並設定errno的錯誤型別。

connect()函式用來與遠端伺服器建立乙個tcp連線,其函式原型為:

#include

#include

int connect(int sockfd,struct sockaddr *serv_addr,int addrlen);

引數sockfd是呼叫socket返回的檔案描述符;引數serv_addr指定遠端伺服器的套接字位址,包括埠和ip位址;引數addrlen設定為套接字位址的長度。函式connect成功執行時返回0;否則返回-1,並設定errno的錯誤型別。

從套接字讀寫資料的read()和write()函式原型為:

#include

#include

int read(int fd,char *buf,int len);

int write(int fd,char *buf,int len);

引數fd指定讀寫操作的套接字描述符;函式read的引數buf指定接收資料緩衝區,函式write的引數buf指定傳送資料緩衝區;引數len指定接收或傳送的資料量大小。

下面我們就利用前面的理論知識具體編寫乙個簡單的基於tcp協議的伺服器/客戶端程式。

伺服器端程式server.c

/*********本程式用於建立服務端程式**************/

#include

#include

#include

#include

#include

#include

#include

#include

int main(int argc, char *argv)

;if(argc!=2)

if((portnumber=atoi(argv[1]))

/* 伺服器端開始建立socket描述符 */

if((sockfd=socket(af_inet,sock_stream,0))==-1)

/* 伺服器端填充 sockaddr_in結構 */

bzero(&server_addr,sizeof(struct sockaddr_in));

server_addr.sin_family=af_inet;

/*ip位址轉換為網路位元組序*/

server_addr.sin_addr.s_addr=htonl(inaddr_any);

/*埠號轉換為網路位元組序*/

server_addr.sin_port=htons(portnumber);

/* **sockfd描述符 */

if(bind(sockfd,(struct sockaddr *)(&server_addr),

sizeof(struct sockaddr))==-1)

/* 監聽sockfd描述符 */

if(listen(sockfd,5)==-1) /*5為請求佇列的最大請求數*/

while(1)

/*inet_ntoa的作用是將乙個32位ipv4位址轉換

為相應的點分十進位制數串*/

printf("server get connection from %s/n",inet_ntoa(client_addr.sin_addr));

/*相客戶端傳送hello字元陣列的內容*/

if(write(new_fd,hello,strlen(hello))==-1)

/* 這個通訊已經結束 */

close(new_fd);

}/* while結尾處*/

close(sockfd);

exit(0);

}

客戶端程式client.chttp://blog.chinaunix.net/u2/67414/showart_1672858.html

傳輸層TCP協議 TCP伺服器 客戶端

tcp伺服器端 客戶端流程 由socket函式建立,隨後用做bind,listen函式的第乙個引數的描述符。乙個伺服器通常僅僅建立乙個監聽套接字,它在該伺服器的生命期內一直存在。由accept函式返回。核心為每個由伺服器程序接受的客戶連線建立乙個已連線套接字 tcp三路握手過程已完成 當伺服器完成對...

基於UDP協議的伺服器 客戶端程式

udp網路程式採用的通訊模型與tcp網路程式模型有很大的不同,具體見圖7 4所示。udp伺服器首先進行初始化操作 呼叫函式socket建立乙個資料報型別的套接字,函式bind將這個套接字與伺服器的公認位址繫結在一起。然後呼叫函式recvfrom接收udp客戶機的資料報。udp客戶機首先呼叫函式soc...

TCP伺服器 客戶端程式

server tcpserver.cpp檔案 include common initsock.h include cinitsock initsock 初始化winsock庫 int main 填充sockaddr in結構 sockaddr in sin sin.sin family af ine...