socket网络编程(1):格式转换函数

1、

   不同类型CPU的计算机存储多字节变量的顺序不同,故主机字节序分为大端序和小端序:

   大端序:高位字节存储在内存的低地址。例如网络传输中使用的字节序。

   小端序:低位字节存储在内存的低地址。例如Inter和AMD的主机。

   如下所示为一个4字节的int分别使用大端序和小端序的存储顺序:

2、

     inet_addr()将一个IPV4类型的点分十进制格式IP地址转换为一个32位网络字节序IP地址。函数原型:

   unsigned long inet_addr(const char *cp);

      htons()将一个unsigned short(端口号)从主机字节序转换为网络字节序。函数原型:

   u_short htons(u_short hostshort);

      htonl()将一个unsigned long从主机字节序转换为网络字节序。

eg:

SOCKADDR_IN addr; 
addr.sin_family = AF_INET;
addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addr.sin_port = htons(6000);

connect(sockClient, (SOCKADDR*)&addr, sizeof(SOCKADDR));

    inet_ntoa()函数将一个in_addr结构体类型转换为点分十进制格式IP地址。函数原型:

  char* inet_ntoa(struct  in_addr in);

    ntohs()函数将一个unsigned short(端口号)从网络字节序转换为主机字节序。函数原型:

  u_short ntohs(u_short netshort);

   ntohl()函数将一个unsigned long从网络字节序转换为主机字节序。

  eg:

SOCKET sockConnect = accept(sockSrv, (sockaddr*)&addrRemote, &len);

char sendBuf[100];
sprintf(sendBuf, "Welcome %s:%d!", inet_ntoa(addrRemote.sin_addr), ntohs(addrRemote.sin_port));

  

   InetPton()、InetNtop()函数与inet_addr()、inet_ntoa()功能一样,不过增加了对IPV6地址类型的支持。

3、

     gethostname():获得主机名。

     gethostbyname()函数可以通过主机名获得主机信息,如主机别名、主机地址等。函数原型:

   struct hostent* gethostbyname(const char *name);

      hostent结构体:

 struct hostent {
	char  *h_name;            /* official name of host */ 主机正式名
	char **h_aliases;         /* alias list */            主机别名
	int    h_addrtype;        /* host address type */     主机地址类型
	int    h_length;          /* length of address */     主机地址长度
	char **h_addr_list;       /* list of addresses */     主机地址
    }
      

 Windows Sockets 2上不再推荐使用gethostbyname(),而是使用getaddrinfo()

 eg: 使用gethostbyname()

#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")

int GetHostInfor()
{
	WORD wVersionRequested = MAKEWORD(1, 1);
	WSADATA wsaData;
	int err;
	
	err = WSAStartup(wVersionRequested, &wsaData);//加载套接字库
	if(err != 0)
		return 1;

	if(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1)
	{
			WSACleanup();
			return 1;
	}
	
    struct hostent *host;

    if((host = gethostbyname("www.google.com")) == NULL)
    {
		int n = WSAGetLastError();
		fprintf(stderr,"获得地址信息失败:%d,%s\n", n,strerror(h_errno));
		return 1;
    }
    fprintf(stdout,"官方主机名:%s\n", host->h_name);

    fprintf(stdout,"主机别名:\n");
    
    char **p;
    for(p=host->h_aliases; *p!=NULL; p++)
    {
		fprintf(stdout,"\t\t%s\n", *p);
    }

    if(host->h_addrtype == AF_INET)
    {
		fprintf(stdout,"主机地址类型: IPV4\n");
    }
    else
    {
		fprintf(stdout,"主机地址类型: IPV6\n");
    }

    fprintf(stdout,"主机地址长度:%d\n", (host->h_length)*8);

    fprintf(stdout,"主机地址:\n");
    
	struct in_addr addr;
	
    for(p=host->h_addr_list; *p!=NULL; p++)
    {	
		addr.s_addr = *(u_long *) *p;
		fprintf(stdout,"\t%s\n",  inet_ntoa(addr));
    }

	return 0;
}

       输出为:

         官方主机名:www.google.com
         主机别名:
         主机地址类型: IPV4
         主机地址长度:32
         主机地址:
                        74.125.128.99
                        74.125.128.105
                        74.125.128.147
                        74.125.128.106
                        74.125.128.103
                        74.125.128.104

    使用getaddrinfo():

#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")

int GetHostInfor(char* pHostName)
{
	WORD wVersionRequested = MAKEWORD(1, 1);
	WSADATA wsaData;
	int err;

	err = WSAStartup(wVersionRequested, &wsaData);//加载套接字库  
	if (err != 0)
		return 1;

	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
		WSACleanup();
		return 1;
	}

	addrinfo* pAddrInfo;
	int iRet = getaddrinfo(pHostName, NULL, NULL, &pAddrInfo);
	if (iRet != 0)
	{
		printf("getaddrinfo() failed:%d\n", iRet);
		return -1;
	}

	addrinfo* ptr = pAddrInfo;
	printf("主机地址:\n");
	while (ptr)
	{
		char ipbuf[32] = { 0 };
		struct sockaddr_in * addr = (struct sockaddr_in *)ptr->ai_addr;
		printf("\t%s\n", inet_ntop(AF_INET, &addr->sin_addr, ipbuf, 16));

		ptr = ptr->ai_next;
	}

	return 0;
}

    gethostbyaddr()函数通过主机地址(网络字节序)获得主机信息。函数原型:

   struct hostent* gethostbyaddr(const char *addr, int len, int type);

      Windows Sockets 2上不再推荐使用gethostbyaddr(),而是使用getnameinfo()函数

4、

     getservbyname()函数获得给定服务名和协议名的相关服务信息。函数原型:

 
struct servent* getservbyname(const char *name, const char *proto);        
 
servent结构体:
struct servent 
    {
	char  *s_name;       /* official service name */  官方服务名
	char **s_aliases;    /* alias list */             别名列表
	int    s_port;       /* port number */            端口号
	char  *s_proto;      /* protocol to use */        使用协议
    }

        eg:

#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")

int GetServInfor()
{
	WORD wVersionRequested = MAKEWORD(1, 1);  
    WSADATA wsaData;  
    int err;  
      
    err = WSAStartup(wVersionRequested, &wsaData);//加载套接字库  
    if(err != 0)  
        return 1;  
  
    if(LOBYTE(wsaData.wVersion)!=1 || HIBYTE(wsaData.wVersion)!=1)  
    {  
            WSACleanup();  
            return 1;  
    }  

    struct servent *ser;

    if((ser = getservbyname("http", NULL)) != NULL)
    {
		fprintf(stdout,"官方服务名:%s\n", ser->s_name);
	    
		fprintf(stdout,"别名:\n");

		char **p;
		for(p = ser->s_aliases; *p!=NULL; p++)
		{
			fprintf(stdout,"\t%s\n", *p);   
		}

		fprintf(stdout,"端口号:%d\n", ntohs(ser->s_port));
	    
		fprintf(stdout,"使用协议:%s\n", ser->s_proto);
    }

	return 0;
}

      输出为:

       官方服务名:http
       别名:
                  www
                  www-http
       端口号:80
       使用协议:tcp

     getservbyport()函数获得给定端口号和协议名的相关服务信息。函数原型:

   struct servent* getservbyport(int port, const char *proto);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值