网络字节序

来源:互联网 发布:win10仿mac桌面dock 编辑:程序博客网 时间:2024/06/05 10:04

    大端模式:从高字节开始存储;小端模式:从低字节开始存储;
     网络协议必须协调一致字节序(网络字节序),同时也要考虑到不同主机的实际情况,所以存在二者之间的转换。
     常见的函数有 htons,htonl,ntohs,ntohl。

查看主机字节序(UNPv1 P64):
#include<stdio.h>#include<stdlib.h>intmain(int argc, char **argv){        union {                short  s;                char   c[sizeof(short)];        } un;//??        un.s = 0x0102;        if (sizeof(short) == 2) {                if (un.c[0] == 1 && un.c[1] == 2)                        printf("big-endian\n");                else if (un.c[0] == 2 && un.c[1] == 1)                        printf("little-endian\n");                else                        printf("unknown\n");        } else                printf("sizeof(short) = %ld\n", sizeof(short));        exit(0);}


点分十进制(presentation)和网络地址结构的二进制格式(numeric)使用 inet_pton , inet_ntop.
#include<arpa/inet.h>
int inet_pton(int family, const char *str, void *addrptr);
const char *inet_ntop(int family, const void *addptr,char *str,size_t len);  注意第二个参数;

简单实现上述功能(IPv4):
#include        <sys/types.h>#include        <sys/socket.h>#include        <netinet/in.h>#include        <arpa/inet.h>#include        <errno.h>#include        <string.h>intmy_inet_pton(int family, const char *strptr, void *addrptr){    if (family == AF_INET) {        struct in_addr  in_val;        if (inet_aton(strptr, &in_val)) {            memcpy(addrptr, &in_val, sizeof(struct in_addr));intmy_inet_pton(int family, const char *strptr, void *addrptr){    if (family == AF_INET) {        struct in_addr  in_val;        if (inet_aton(strptr, &in_val)) {            memcpy(addrptr, &in_val, sizeof(struct in_addr));            return (1);        }                return(0);    }        errno = EAFNOSUPPORT;    return (-1);}const char *my_inet_ntop(int family, const void *addrptr, char *strptr, size_t len){        const u_char *p = (const u_char *) addrptr;        if (family == AF_INET) {                char    temp[INET_ADDRSTRLEN];                snprintf(temp, sizeof(temp), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);                if (strlen(temp) >= len) {                        errno = ENOSPC;                        return (NULL);                }                strcpy(strptr, temp);                return (strptr);        }        errno = EAFNOSUPPORT;        return (NULL);}int main(){        char buf[INET_ADDRSTRLEN]={0};        struct sockaddr_in addr;        addr.sin_family=AF_INET;        addr.sin_addr.s_addr = inet_addr("192.168.4.135");        printf("%s\n",my_inet_ntop(AF_INET,(const void *)&addr.sin_addr,buf,sizeof(buf)));//      printf("%s\n",inet_ntop(AF_INET,(const void *)&addr.sin_addr,buf,sizeof(buf)));        return 0;}


   


对于上面的调用必须确定是IPv4或IPv6的地址(&addr6.sin6_addr)可以利用包裹函数,通用处理(sock_ntop):
#include "util.h"#ifdef  HAVE_SOCKADDR_DL_STRUCT#include        <net/if_dl.h>#endif/* include sock_ntop */char *sock_ntop(const struct sockaddr *sa, socklen_t salen){    char                portstr[8];    static char str[128];               /* Unix domain is largest */        switch (sa->sa_family) {        case AF_INET: {                struct sockaddr_in      *sin = (struct sockaddr_in *) sa;                if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL)                        return(NULL);                if (ntohs(sin->sin_port) != 0) {                        snprintf(portstr, sizeof(portstr), ":%d", ntohs(sin->sin_port));                        strcat(str, portstr);                }                return(str);        }/* end sock_ntop */#ifdef  IPV6        case AF_INET6: {                struct sockaddr_in6     *sin6 = (struct sockaddr_in6 *) sa;                str[0] = '[';                if (inet_ntop(AF_INET6, &sin6->sin6_addr, str + 1, sizeof(str) - 1) == NULL)                        return(NULL);                if (ntohs(sin6->sin6_port) != 0) {                        snprintf(portstr, sizeof(portstr), "]:%d", ntohs(sin6->sin6_port));                        strcat(str, portstr);                        return(str);                }                return (str + 1);        }#endif#ifdef  AF_UNIX        case AF_UNIX: {                struct sockaddr_un      *unp = (struct sockaddr_un *) sa;                        /* OK to have no pathname bound to the socket: happens on                           every connect() unless client calls bind() first. */                if (unp->sun_path[0] == 0)                        strcpy(str, "(no pathname bound)");                else                        snprintf(str, sizeof(str), "%s", unp->sun_path);                return(str);        }#endif#ifdef  HAVE_SOCKADDR_DL_STRUCT        case AF_LINK: {                struct sockaddr_dl      *sdl = (struct sockaddr_dl *) sa;                if (sdl->sdl_nlen > 0)                        snprintf(str, sizeof(str), "%*s (index %d)",                                         sdl->sdl_nlen, &sdl->sdl_data[0], sdl->sdl_index);                else                        snprintf(str, sizeof(str), "AF_LINK, index=%d", sdl->sdl_index);                return(str);        }#endif        default:                snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d",                                 sa->sa_family, salen);                return(str);        }    return (NULL);}char *Sock_ntop(const struct sockaddr *sa, socklen_t salen){        char    *ptr;        if ( (ptr = sock_ntop(sa, salen)) == NULL)                perror("sock_ntop error");      /* inet_ntop() sets errno */        return(ptr);}




测试:
#include "util.h"int main(){        struct sockaddr_in addr;        addr.sin_family = AF_INET;        addr.sin_addr.s_addr = inet_addr("192.168.4.135");        addr.sin_port = htons(13);        printf("%s\n",Sock_ntop((const struct sockaddr *)&addr,sizeof(addr)));        return 0;}


0 0