Linux網路程式設計常用函式

2021-05-08 02:49:14 字數 4963 閱讀 6483

計算機資料儲存有兩種位元組優先順序:高位位元組優先和低位位元組優先。internet上資料以高位位元組優先順

序在網路上傳輸,所以對於在內部是以低位位元組優先方式儲存資料的機器,在internet上傳輸資料時就需

要進行轉換。

我們要討論的第乙個結構型別是:struct sockaddr,該型別是用來儲存socket資訊的:

struct sockaddr ;

sa_family一般為af_inet;sa_data則包含該socket的ip位址和埠號。

另外還有一種結構型別:

struct sockaddr_in ;

這個結構使用更為方便。sin_zero(它用來將sockaddr_in結構填充到與struct sockaddr同樣的長度)應該用bzero()或memset()函式將其置為零。指向sockaddr_in 的指標和指向sockaddr的指標可以相互轉換,這意味著如果乙個函式所需引數型別是sockaddr時,你可以在函式呼叫的時候將乙個指向 sockaddr_in的指標轉換為指向sockaddr的指標;或者相反。sin_family通常被賦af_inet;sin_port和 sin_addr應該轉換成為網路位元組優先順序;而sin_addr則不需要轉換。

我們下面討論幾個位元組順序轉換函式:

htons()--"host to network short" ; htonl()--"host to network long"

ntohs()--"network to host short" ; ntohl()--"network to host long"

在這裡, h表示"host" ,n表示"network",s 表示"short",l表示 "long"。

開啟socket 描述符、建立繫結並建立連線

socket函式原型為:

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

domain引數指定socket的型別,一般為af_inet,type可以是sock_stream 或sock_dgram,分別表示tcp連線和udp連線;protocol通常賦值"0"。socket()呼叫返回乙個整型socket描述符,你可 以在後面的呼叫使用它。

一旦通過socket呼叫返回乙個socket描述符,你應該將該socket與你本機上的乙個埠相關聯(往往當你在設計伺服器端程式時需要呼叫該函式。隨後你就可以在該埠監聽服務請求;而客戶端一般無須呼叫該函式)。

bind函式原型為:

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

sockfd是乙個socket描述符,my_addr是乙個指向包含有本機ip位址及埠號等資訊的sockaddr型別的指標;addrlen常被設定為sizeof(struct sockaddr)。

my_addr.sin_port = 0; /* 系統隨機選擇乙個未被使用的埠號 */

my_addr.sin_addr.s_addr = inaddr_any; /* 填入本機ip位址 */

通過將my_addr.sin_port置為0,函式會自動為你選擇乙個未占用的埠來使用。同樣,通過將 my_addr.sin_addr.s_addr置為inaddr_any,系統會自動填入本機ip位址。bind()函式在成功被呼叫時返回0;遇到錯 誤時返回"-1"並將errno置為相應的錯誤號。另外要注意的是,

當呼叫函式時,一般不要將埠號置為小於1024的值,因為1~1024是保留埠號 ,你可以使用大於1024中任何乙個沒有被占用的埠號。

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

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

sockfd是目的伺服器的sockt描述符;serv_addr是包含目的機ip位址和埠號的指標。遇到錯誤時返回-1,並且errno中包含相應 的錯誤碼。進行客戶端程式設計無須呼叫bind(),因為這種情況下只需知道目的機器的ip位址,而客戶通過哪個埠與伺服器建立連線並不需要關心,核心 會自動選擇乙個未被占用的埠供客戶端來使用。

listen()——監聽是否有服務請求

在伺服器端程式中,當socket與某一埠**以後,就需要監聽該埠,以便對到達的服務請求加以處理。

int listen(int sockfd, int backlog);

sockfd是socket系統呼叫返回的socket 描述符;backlog指定在請求佇列中允許的最大請求數,進入的連線請求將在佇列中等待accept()它們(參考下文)。backlog對佇列中等待 服務的請求的數目進行了限制,大多數系統預設值為20。當listen遇到錯誤時返回-1,errno被置為相應的錯誤碼。

故伺服器端程式通常按下列順序進行函式呼叫:

socket(); bind(); listen(); /* accept() goes here */

accept()——連線埠的服務請求。

當某個客戶端試圖與伺服器監聽的埠連線時,該連線請求將排隊等待伺服器 accept()它。通過呼叫accept()函式為其建立乙個連線,accept()函式將返回乙個新的socket描述符,來供這個新連線來使用。而 伺服器可以繼續在以前的那個 socket上監聽,同時可以在新的socket描述符上進行資料send()(傳送)和recv()(接收)操作:

int accept(int sockfd, void *addr, int *addrlen);

sockfd是被監聽的socket描述符,addr通常是乙個指向sockaddr_in變數的指標,該變數用來存放提出連線請求服務的主機的資訊 (某台主機從某個埠發出該請求);addrten通常為乙個指向值為sizeof(struct sockaddr_in)的整型指標變數。錯誤發生時返回乙個-1並且設定相應的errno值。

send()和recv()——資料傳輸

這兩個函式是用於面向連線的socket上進行資料傳輸。

send()函式原型為:

int send(int sockfd, const void *msg, int len, int flags);

sockfd是你想用來傳輸資料的socket描述符,msg是乙個指向要傳送資料的指標。

len是以位元組為單位的資料的長度。flags一般情況下置為0(關於該引數的用法可參照man手冊)。

char *msg = "beej was here!"; int len, bytes_sent; ... ...

len = strlen(msg); bytes_sent = send(sockfd, msg,len,0); ... ...

send()函式返回實際上傳送出的位元組數,可能會少於你希望傳送的資料。所以需要對send()的返回值進行測量。當send()返回值與len不匹配時,應該對這種情況進行處理。

recv()函式原型為:

int recv(int sockfd,void *buf,int len,unsigned int flags);

sockfd是接受資料的socket描述符;buf 是存放接收資料的緩衝區;len是緩衝的長度。flags也被置為0。recv()返回實際上接收的位元組數,或當出現錯誤時,返回-1並置相應的errno值。

sendto()和recvfrom()——利用資料報方式進行資料傳輸

int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);

該函式比send()函式多了兩個引數,to表示目地機的ip位址和埠號資訊,而tolen常常被賦值為sizeof (struct sockaddr)。sendto 函式也返回實際傳送的資料位元組長度或在出現傳送錯誤時返回-1。

recvfrom()函式原型為:

int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);

from是乙個struct sockaddr型別的變數,該變數儲存源機的ip位址及埠號。fromlen常置為sizeof(struct sockaddr)。當recvfrom()返回時,fromlen包含實際存入from中的資料位元組數。recvfrom()函式返回接收到的位元組數或 當出現錯誤時返回-1,並置相應的errno。

應注意的一點是,當你對於資料報socket呼叫了connect()函式時,你也可以利用send()和recv()進行資料傳輸,但該socket仍然是資料報socket,並且利用傳輸層的udp服務。但在傳送或接收資料報時,核心會自動為之加上目地和源位址資訊。

close()和shutdown()——結束資料傳輸

當所有的資料操作結束以後,你可以呼叫close()函式來釋放該socket,從而停止在該socket上的任何資料操作:close(sockfd);

你也可以呼叫shutdown()函式來關閉該socket。該函式允許你只停止在某個方向上的資料傳輸,而乙個方向上的資料傳輸繼續進行。如你可以關閉某socket的寫操作而允許繼續在該socket上接受資料,直至讀入所有資料。

int shutdown(int sockfd,int how);

sockfd的含義是顯而易見的,而引數 how可以設為下列值:

·0-------不允許繼續接收資料

·1-------不允許繼續傳送資料

·2-------不允許繼續傳送和接收資料,均為允許則呼叫close ()

shutdown在操作成功時返回0,在出現錯誤時返回-1(並置相應errno)。

dns——網域名稱服務相關函式

struct hostent *gethostbyname(const char *name);

函式返回一種名為hosten的結構型別,它的定義如下:

struct hostent ;

#define h_addr h_addr_list[0] /*在h-addr-list中的第乙個位址*/

Linux 網路程式設計常用函式詳解

sendto 經socket傳送資料 相關函式 send sendmsg,recv recvfrom socket 表頭檔案 include sys types.h include sys socket.h 定義函式 int sendto int s const void msg,int len,u...

linux 網路程式設計常用函式及流程

一 網路程式設計之tcp流程 服務端 socket bind listen while 1 close 客戶端 socket connect send recv close 二 網路程式設計常用函式 伺服器端 標頭檔案包含 include include include include includ...

linux網路程式設計常用函式詳解與例項

常用的網路命令 netstat telnet telnet是乙個用來遠端控制的程式,但是我們完全可以用這個程式來除錯我們的服務端程式的.比如我們的伺服器程式在監聽8888埠,我們可以用telnet localhost 8888來檢視服務端的狀況.網路函式描述和例項 int socket int do...