sendto() 和 recvfrom()函數(shù)
“這很不錯啊”,你說,“但是你還沒有講無連接數(shù)據(jù)報套接字呢?” 沒問題,現(xiàn)在我們開始這個內(nèi)容。
既然數(shù)據(jù)報套接字不是連接到遠程主機的,那么在我們發(fā)送一個包之 前需要什么信息呢? 不錯,是目標(biāo)地址!看看下面的:
int sendto(int sockfd, const void *msg, int len, unsigned int flags,
const struct sockaddr *to, int tolen);
你已經(jīng)看到了,除了另外的兩個信息外,其余的和函數(shù) send() 是一樣 的。 to 是個指向數(shù)據(jù)結(jié)構(gòu) struct sockaddr 的指針,它包含了目的地的 IP 地址和端口信息。tolen 可以簡單地設(shè)置為 sizeof(struct sockaddr)。 和函數(shù) send() 類似,sendto() 返回實際發(fā)送的字節(jié)數(shù)(它也可能小于 你想要發(fā)送的字節(jié)數(shù)!),或者在錯誤的時候返回 -1。
相似的還有函數(shù) recv() 和 recvfrom()。recvfrom() 的定義是這樣的:
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
又一次,除了兩個增加的參數(shù)外,這個函數(shù)和 recv() 也是一樣的。from 是一個指向局部數(shù)據(jù)結(jié)構(gòu) struct sockaddr 的指針,它的內(nèi)容是源機器的 IP 地址和端口信息。fromlen 是個 int 型的局部指針,它的初始值為 sizeof(struct sockaddr)。函數(shù)調(diào)用返回后,fromlen 保存著實際儲存在 from 中的地址的長度。
recvfrom() 返回收到的字節(jié)長度,或者在發(fā)生錯誤后返回 -1。
記住,如果你用 connect() 連接一個數(shù)據(jù)報套接字,你可以簡單的調(diào) 用 send() 和 recv() 來滿足你的要求。這個時候依然是數(shù)據(jù)報套接字,依 然使用 UDP,系統(tǒng)套接字接口會為你自動加上了目標(biāo)和源的信息。
--------------------------------------------------------------------------------
close()和shutdown()函數(shù)
你已經(jīng)整天都在發(fā)送 (send()) 和接收 (recv()) 數(shù)據(jù)了,現(xiàn)在你準(zhǔn)備關(guān) 閉你的套接字描述符了。這很簡單,你可以使用一般的 Unix 文件描述符 的 close() 函數(shù):
close(sockfd);
它將防止套接字上更多的數(shù)據(jù)的讀寫。任何在另一端讀寫套接字的企 圖都將返回錯誤信息。
如果你想在如何關(guān)閉套接字上有多一點的控制,你可以使用函數(shù) shutdown()。它允許你將一定方向上的通訊或者雙向的通訊(就象close()一 樣)關(guān)閉,你可以使用:
int shutdown(int sockfd, int how);
sockfd 是你想要關(guān)閉的套接字文件描述復(fù)。how 的值是下面的其中之 一:
0 – 不允許接受
1 – 不允許發(fā)送
2 – 不允許發(fā)送和接受(和 close() 一樣)
shutdown() 成功時返回 0,失敗時返回 -1(同時設(shè)置 errno。) 如果在無連接的數(shù)據(jù)報套接字中使用shutdown(),那么只不過是讓 send() 和 recv() 不能使用(記住你在數(shù)據(jù)報套接字中使用了 connect 后 是可以使用它們的)。
--------------------------------------------------------------------------------
getpeername()函數(shù)
這個函數(shù)太簡單了。
它太簡單了,以至我都不想單列一章。但是我還是這樣做了。 函數(shù) getpeername() 告訴你在連接的流式套接字上誰在另外一邊。函 數(shù)是這樣的:
#include
int getpeername(int sockfd, struct sockaddr *addr, int *addrlen);
sockfd 是連接的流式套接字的描述符。addr 是一個指向結(jié)構(gòu) struct sockaddr (或者是 struct sockaddr_in) 的指針,它保存著連接的另一邊的 信息。addrlen 是一個 int 型的指針,它初始化為 sizeof(struct sockaddr)。 函數(shù)在錯誤的時候返回 -1,設(shè)置相應(yīng)的 errno。
一旦你獲得它們的地址,你可以使用 inet_ntoa() 或者 gethostbyaddr() 來打印或者獲得更多的信息。但是你不能得到它的帳號。(如果它運行著愚 蠢的守護進程,這是可能的,但是它的討論已經(jīng)超出了本文的范圍,請參 考 RFC-1413 以獲得更多的信息。)
--------------------------------------------------------------------------------
gethostname()函數(shù)
甚至比 getpeername() 還簡單的函數(shù)是 gethostname()。它返回你程 序所運行的機器的主機名字。然后你可以使用 gethostbyname() 以獲得你 的機器的 IP 地址。
下面是定義:
#include
int gethostname(char *hostname, size_t size);
參數(shù)很簡單:hostname 是一個字符數(shù)組指針,它將在函數(shù)返回時保存
主機名。size是hostname 數(shù)組的字節(jié)長度。
函數(shù)調(diào)用成功時返回 0,失敗時返回 -1,并設(shè)置 errno。
--------------------------------------------------------------------------------