e
int main() { char ip[] = "192.168.0.101"; struct in_addr myaddr; /* inet_aton */ int iRet = inet_aton(ip, &myaddr); printf("%x\n", myaddr.s_addr); /* inet_addr */ printf("%x\n", inet_addr(ip)); /* inet_pton */ iRet = inet_pton(AF_INET, ip, &myaddr); printf("%x\n", myaddr.s_addr); myaddr.s_addr = 0xac100ac4; /* inet_ntoa */ printf("%s\n", inet_ntoa(myaddr)); /* inet_ntop */ inet_ntop(AF_INET, &myaddr, ip, 16); puts(ip); return 0; }
名字地址转化
通常,人们在使用过程中都不愿意记忆冗长的IP地址,尤其到Ipv6时,地址长度多达128位,那时就更加不可能一次性记忆那么长的IP地址了。因此,使用主机名或域名将会是很好的选择。主机名与域名的区别:主机名通常在局域网里面使用,通过/etc/hosts文件,主机名可以解析到对应的ip;域名通常是再internet上使用。域名例如:www.baidu.com
在linux中,有一些函数可以实现主机名和地址的转化,最常见的有gethostbyname()、gethostbyaddr()等,它们都可以实现IPv4和IPv6的地址和主机名之间的转化。其中gethostbyname()是将主机名转化为IP地址,gethostbyaddr()则是逆操作,是将IP地址转化为主机名。
函数原型:
#include
struct hostent* gethostbyname(const char* hostname);
struct hostent* gethostbyaddr(const char* addr, size_t len, int family);
结构体:
struct hostent
{
char *h_name; /*正式主机名*/
char **h_aliases; /*主机别名*/
int h_addrtype; /*主机IP地址类型 IPv4为AF_INET*/
int h_length; /*主机IP地址字节长度,对于IPv4是4字节,即32位*/
char **h_addr_list; /*主机的IP地址列表*/
}
#define h_addr h_addr_list[0] /*保存的是ip地址*/
函数gethostbyname():用于将域名(www.baidu.com)或主机名转换为IP地址。参数hostname指向存放域名或主机名的字符串。
函数gethostbyaddr():用于将IP地址转换为域名或主机名。参数addr是一个IP地址,此时这个ip地址不是普通的字符串,而是要通过函数inet_aton()转换。len为IP地址的长度,AF_INET为4。family可用AF_INET:Ipv4或AF_INET6:Ipv6。
#include
#include
#include
int main(int argc, char **argv) { char *ptr, **pptr; struct hostent *hptr; char str[32] = {'\0'}; /* 取得命令后第一个参数,即要解析的域名或主机名 */ ptr = argv[1]; //如www.baidu.com /* 调用gethostbyname()。结果存在hptr结构中 */ if((hptr = gethostbyname(ptr)) == NULL) { printf(" gethostbyname error for host:%s\n", ptr); return 0; } /* 将主机的规范名打出来 */ printf("official hostname:%s\n",hptr->h_name); /* 主机可能有多个别名,将所有别名分别打出来 */ for(pptr = hptr->h_aliases; *pptr != NULL; pptr++) printf(" alias:%s\n",*pptr); /* 根据地址类型,将地址打出来 */ switch(hptr->h_addrtype) { case AF_INET: case AF_INET6: pptr=hptr->h_addr_list; /* 将刚才得到的所有地址都打出来。其中调用了inet_ntop()函数 */ for(; *pptr!=NULL; pptr++) printf(" address:%s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); printf(" first address: %s\n", inet_ntop(hptr->h_addrtype, hptr->h_addr, str, sizeof(str))); break; default: printf("unknown address type\n"); break; } return 0; }
socket编程
使用TCP协议的流程图
服务器端:
1. 头文件包含:
#include
#include
#include
#include
#include
#include
#include
#include
2. socket函数:生成一个套接口描述符(被看作一个文件)。
原型:int socket(int domain,int type,int protocol);
参数:domain{ AF_INET:Ipv4 网络协议 AF_INET6:IPv6网络协议}
type{tcp:SOCK_STREAM udp:SOCK_DGRAM}
protocol 指定socket所使用的传输协议编号。通常为0.
返回值:成功则返回套接口描述符,失败返回-1。
常用实例:int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd == -1){perror("socket");exit(-1);}
3. bind函数:用来绑定一个端口号和IP地址,使套接口与指定的端口号和IP地址相关联。
原型:int bind(int sockfd,struct sockaddr * my_addr,int addrlen);
参数:sockfd为前面socket的返回值。
my_addrà为结构体指针变量
对于不同的socket domain定义了一个通用的数据结构
struct sockaddr //此结构体不常用
{
unsigned short int sa_family; //调用socket()时的domain参数,即AF_INET值。
char sa_data[14]; //最多使用14个字符长度
};
此sockaddr结构会因使用不同的socket domain而有不同结构定义,
例如使用AF_INET domain,其socketaddr结构定义便为
struct sockaddr_in //常用的结构体
{
unsigned short int sin_family; //即为