网络字节序
2014-03-03 20:49
204 查看
大端模式:从高字节开始存储;小端模式:从低字节开始存储;
网络协议必须协调一致字节序(网络字节序),同时也要考虑到不同主机的实际情况,所以存在二者之间的转换。
常见的函数有 htons,htonl,ntohs,ntohl。
查看主机字节序(UNPv1 P64):
点分十进制(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):
对于上面的调用必须确定是IPv4或IPv6的地址(&addr6.sin6_addr)可以利用包裹函数,通用处理(sock_ntop):
测试:
网络协议必须协调一致字节序(网络字节序),同时也要考虑到不同主机的实际情况,所以存在二者之间的转换。
常见的函数有 htons,htonl,ntohs,ntohl。
查看主机字节序(UNPv1 P64):
#include<stdio.h> #include<stdlib.h> int main(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> int my_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)); int my_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 H***E_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 H***E_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; }
相关文章推荐
- 关于socket的Accept阻塞模式的退出方法分析
- CGIC简明教程目录(CGI篇)
- 网络和计应12级电子商务学习
- 第四章 网络层
- Go语言linux下构造tcp数据包(不使用net包和Cgo)
- 网络新协议梳理
- 一、【word2vec学习路线】神经网络语言模型
- 网络判断的监听器
- HttpClient拉取连载小说
- TCP/IP、Http、Socket的区别
- Building a Non-blocking TCP server using OTP principles
- linux网络编程之TCP/IP基础(二):利用ARP和ICMP协议解释ping命令
- linux网络编程之TCP/IP基础(一):TCP/IP协议栈与数据报封装
- IP网络存储iscsi
- 2014新规划-目标(转zfpp25_:http://blog.csdn.net/lizhongfu2013)
- 【Web】HttpServletRequest request 相关方法 得到路径
- HTTP协议 (二) 基本认证
- 检查网络状态
- Servlet(二)--session管理--HttpSession
- TOSSIM仿真之网络配置