電腦店訊
1 字節轉換函數
在網絡上面有著許多類型的機器,這些機器在表示數據的字節順序是不同的, 比如i386芯片是低字節在內存地址的低端,高字節在高端,而alpha芯片卻相反. 為了統一起來,在Linux下面,有專門的字節轉換函數.
unsigned long int htonl(unsigned long int hostlong)
unsigned short int htons(unisgned short int hostshort)
unsigned long int ntohl(unsigned long int netlong)
unsigned short int ntohs(unsigned short int netshort)
在這四個轉換函數中,h 代表host, n 代表network.s 代表short l 代表long
第一個函數的意義是將本機器上的long數據轉化為網絡上的long. 其他幾個函數的意義也差不多.
2 IP和域名的轉換
在網絡上標志一台機器可以用IP或者是用域名.那麼我們怎麼去進行轉換呢?
struct hostent *gethostbyname(const char *hostname)
struct hostent *gethostbyaddr(const char *addr,int len,int type)
在中有struct hostent的定義
struct hostent{
char *h_name; /* 主機的正式名稱 */
char *h_aliases; /* 主機的別名*/
int h_addrtype; /* 主機的地址類型 AF_INET*/
int h_length; /* 主機的地址長度 對於IP4 是4字節32位*/
char **h_addr_list; /* 主機的IP地址列表*/
}
#define h_addr h_addr_list[0] /* 主機的第一個IP地址*/
gethostbyname可以將機器名(如linux.yessun.com)轉換為一個結構指針.在這個結構裡面儲存了域名的信息gethostbyaddr可以將一個32位的IP地址(C0A80001)轉換為結構指針.
這兩個函數失敗時返回NULL 且設置h_errno錯誤變量,調用h_strerror()可以得到詳細的出錯信息
3 字符串的IP和32位的IP轉換.
在網絡上面我們用的IP都是數字加點(192.168.0.1)構成的, 而在struct in_addr結構中用的是32位的IP, 我們上面那個32位IP(C0A80001)是的192.168.0.1 為了轉換我們可以使用下面兩個函數
int inet_aton(const char *cp,struct in_addr *inp)
char *inet_ntoa(struct in_addr in)
函數裡面a 代表ascii n 代表network.第一個函數表示將a.b.c.d的IP轉換為32位的IP,存儲在inp指針裡面.第二個是將32位IP轉換為a.b.c.d的格式.
4 服務信息函數
在網絡程序裡面我們有時候需要知道端口.IP和服務信息.這個時候我們可以使用以下幾個函數
int getsockname(int sockfd,struct sockaddr *localaddr,int *addrlen)
int getpeername(int sockfd,struct sockaddr *peeraddr, int *addrlen)
struct servent *getservbyname(const char *servname,const char *protoname)
struct servent *getservbyport(int port,const char *protoname)
struct servent
{
char *s_name; /* 正式服務名*/
char **s_aliases; /* 別名列表*/
int s_port; /* 端口號*/
char *s_proto; /* 使用的協議*/
}
一般我們很少用這幾個函數.對應客戶端,當我們要得到連接的端口號時在connect調用成功後使用可得到系統分配的端口號.對於服務端,我們用INADDR_ANY填充後,為了得到連接的IP我們可以在accept調用成功後使用而得到IP地址.
在網絡上有許多的默認端口和服務,比如端口21對ftp80對應WWW.為了得到指定的端口號的服務我們可以調用第四個函數,相反為了得到端口號可以調用第三個函數.
5 一個例子
CODE:
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
int main(int argc ,char **argv)
{
struct sockaddr_in addr;
struct hostent *host;
char **alias;
if(argc<2)
{
fprintf(stderr,"Usage:%s hostname|ip..\n\a",argv[0]);
exit(1);
}
argv++;
for(;*argv!=NULL;argv++)
{
/* 這裡我們假設是IP*/
if(inet_aton(*argv,&addr.sin_addr)!=0)
{
host=gethostbyaddr((char *)&addr.sin_addr,4,AF_INET);
printf("Address information of Ip %s\n",*argv);
}
else
{
/* 失敗,難道是域名?*/
host=gethostbyname(*argv); printf("Address information
of host %s\n",*argv);
}
if(host==NULL)
{
/* 都不是,算了不找了*/
fprintf(stderr,"No address information of %s\n",*argv);
continue;
}
printf("Official host name %s\n",host->h_name);
printf("Name aliases:");
for(alias=host->h_aliases;*alias!=NULL;alias++)
printf("%s ,",*alias);
printf("\nIp address:");
for(alias=host->h_addr_list;*alias!=NULL;alias++)
printf("%s ,",inet_ntoa(*(struct in_addr *)(*alias)));
}
}
在這個例子裡面,為了判斷用戶輸入的是IP還是域名我們調用了兩個函數,第一次我們假設輸入的是IP所以調用inet_aton, 失敗的時候,再調用gethostbyname而得到信息.