前面我們初步學習了資料流套接字程式設計的一些基礎知識,下面我們來學習如何具體實現這一網路通訊流程。首先我們看一下使用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...