【UNIX网络编程(一)】套接字地址结构、网络字节顺序和地址转换功能
介绍:应该用在网络编程实现每个套接字地址结构。所以主套接字地址结构后前提网络计划编制,地址结构可以在两个方向上发送:从工艺到内核和内核处理。构中的二进制值之间进行转换。
大多数套接字函数都须要一个指向套接字地址结构的指针作为參数。不同协议都有自己的套接字地址结构。
通用的套接字地址结构是sockaddr。IPv4套接字地址结构是定义在头文件<netinet/in.h>中的sockaddr_in,其POSIX定义例如以下:
struct in_addr{
in_addr_t s_addr; /*32-bit IPv4 address*/
}; /*network byte ordered*/
struct sockaddr_in{
unit8_t sin_len; /*length of structure(16)*/
sa_family_t sin_family; /*AF_INET*/
in_port_t sin_port; /*16-bit TCP or UDP port number*/
/*network byte ordered*/
struct in_addr sin_addr; /*32-bit IPv4 address, network byte ordered*/
char sin_zero[8];
};
POSIX规范仅仅须要结构中的3个字段:sin_family、sin_addr和sin_port。
它们的数据类型也都在上面给出了。
注意:32位IPv4地址存在两种不同的訪问方法。举例来说,假设serv定义为某个网络套接字地址结构,那么serv.sin_addr将按in_addr结构引用当中的32位IPv4地址。而serv.sin_addr.s_addr将按in_addr_t(一般是一个无符号的32位整数)引用同一个32位IPv4地址。因此,必须正确使用IPV4地址。尤其是将它作为函数的參数时。由于编译器对传递结构和传递整数的处理时全然不同的。
通用套接字地址结构sockaddr定义在<sys/socket.h>头文件里。
struct sockaddr{
unit8_t sa_len; /*address family:AF_xxx value*/
sa_family_t sa_family; /*protocol-specific address*/
};
套接字函数被定义为以指向通用套接字地址结构的指针作为參数。如int bind(int, struct sockaddr *, socklen_t);因此。调用这些函数时必须将指向特定于协议的套接字地址结构的指针进行强制类型转换,变成指向某个通用套接字地址结构的指针。如struct
sockaddr_in serv; bind(sockfd, (struct sockaddr *)&serv, sizeof(serv));该技巧差点儿用在了全部套接字函数中,一定要熟练掌握。
套接字地址结构有5种:IPv4、IPv6、Unix域、数据链路和存储。
地址转换函数,在ASCII字符串与网络字节序的二进制值之间转换网际地址。
inet_aton、inet_addr(已经不用了)和inet_ntoa在点分十进制数串(比如“206.168.112.96”)与它长度为32位的网络字节序二进制值间转换IPv4地址。而inet_pton和inet_ntop对于IPv4和IPv6地址都适用。
#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr); /*返回:若字符串有效则为1,否则为0*/
char *inet_ntoa(struct in_addr inaddr); /*返回:指向一个点分十进制数串的指针*/
inet_aton将strptr所指字符串转换为一个32位的网络字节序二进制值,并通过指针addrptr来存储。若成功为1,否则为0。inet_ntoa函数将一个32位的网络字节序二进制IPv4地址转换成对应的点分十进制数串,由该函数的返回值所指向的字符串驻留在静态内存中。注意,该函数以一个结构而不是该结构的指针作为其參数。
#include <arpa/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
两个函数的family參数既能够是AF_INET,也能够是AF_INET6。假设以不被支持的地址族作为family參数。这两个函数就返回一个错误,并将errno置位EAFNOSUPPORT。
第一个函数尝试转换由strptr指针所指的字符串,并通过addrptr指针存放二进制结果。若成功则返回值为1。否则假设对所指定的family而言输入的字符串不是有效的表达格式,返回0。inet_ntop进行相反的转换,从数值格式转换为表达式。
既然上面提到了网络字节序,那么就要说一说网络字节序与主机字节序的差别。
内存中存储两个字节有两种方法:一种是将迪许字节存储在起始地址,称为小端字节序;还有一种是将高端字节存储在起始地址。称为大端字节序。
主机字节序是系统所用的字节序,能够用下列程序測试:
#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("unkonwn\n");
}else
printf("sizeof(short) = %d\n", sizeof(short));
exit(0);
}
网络字节序和主机字节序之间相互转换的函数例如以下:
#include <netinet/in.h>
unit16_t htons(unit16_t host16bitvalue);
unit32_t htons(unit32_t host32bitvalue);/*返回网络字节序的值*/
unit16_t ntohs(unit16_t net16bitvalue);
unit32_t ntohs(unit32_t net32bitvalue); /*返回主机字节序的值*/
应该把s视为一个16位的值(比如TCP或UDPport号)。把l视为一个32位的值(比如IPv4地址);
除了协议首部中各个字段的字节序问题外,还有网络分组中所含数据的字节序问题。
补充:字节操纵函数
操纵多字节字段的函数有两组:它们既不正确数据做解释,也不如果数据是以空字符结束的字符串。
#include <string.h>
void bzero(void *dest, size_t nbytes);
void bcopy(const void *src, void *dest, size_t bytes);
int bcmp(const void *ptr1, const void *ptr2, size_t nbytes);
#include <string.h>
void *memset(void *dest, int c, size_t len);
void *memcpy(void *dest, const void *src, size_t nbytes);
int memcmp(const void *ptr1, const void *ptr2, size_t nbytes);
【UNIX网络编程(一)】套接字地址结构、网络字节顺序和地址转换功能的更多相关文章
- UNIX网络编程——原始套接字的魔力【续】
如何从链路层直接发送数据帧 上一篇里面提到的是从链路层"收发"数据,该篇是从链路层发送数据帧. 上一节我们主要研究了如何从链路层直接接收数据帧,可以通过bind函数来将原始套接字绑 ...
- UNIX网络编程——原始套接字(dos攻击)
原始套接字(SOCK_RAW).应用原始套接字,我们可以编写出由TCP和UDP套接字不能够实现的功能. 注意原始套接字只能够由有 root权限的人创建. 可以参考前面的博客<<UNIX网络 ...
- unix网络编程——TCP套接字编程
TCP客户端和服务端所需的基本套接字.服务器先启动,之后的某个时刻客户端启动并试图连接到服务器.之后客户端向服务器发送请求,服务器处理请求,并给客户端一个响应.该过程一直持续下去,直到客户端关闭,给服 ...
- UNIX网络编程——原始套接字SOCK_RAW
实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM).而这些数据包都是由系统提供的协议栈实现, ...
- UNIX网络编程——原始套接字的魔力【下】
可以接收链路层MAC帧的原始套接字 前面我们介绍过了通过原始套接字socket(AF_INET, SOCK_RAW, protocol)我们可以直接实现自行构造整个IP报文,然后对其收发.提醒一点,在 ...
- UNIX网络编程——原始套接字的魔力【上】
基于原始套接字编程 在开发面向连接的TCP和面向无连接的UDP程序时,我们所关心的核心问题在于数据收发层面,数据的传输特性由TCP或UDP来保证: 也就是说,对于TCP或UDP的程序开发,焦点在Dat ...
- UNIX网络编程——通用套接字选项
1. SO_BROADCAST 套接字选项 本选项开启或禁止进程发送广播消息的能力.只有数据报套接字支持广播,并且还必须是在支持广播消息的网络上(例如以太网,令牌环网等).我们不可能在点对点链路上进行 ...
- <unix网络编程>UDP套接字编程
典型的UDP客户/服务器程序的函数调用如下: 1.缓冲区 发送缓冲区用虚线表示,任何UDP套接字都有发送缓冲区,不过该缓冲区仅能表示写到该套接字的UDP数据报的上限.如果应用进程写一个大于套接字缓冲区 ...
- UNIX网络编程——设置套接字超时
在涉及套接字的I/O操作上设置超时的方法有以下3种: 调用alarm,它在指定超时期时产生SIGALRM信号.这个方法涉及信号处理,而信号处理在不同的实现上存在差异,而且可能干扰进程中现有的alarm ...
- TCP/IP网络编程之套接字类型与协议设置
套接字与协议 如果相隔很远的两人要进行通话,必须先决定对话方式.如果一方使用电话,另一方也必须使用电话,而不是书信.可以说,电话就是两人对话的协议.协议是对话中使用的通信规则,扩展到计算机领域可整理为 ...
随机推荐
- Windows下Jekyll安装
一直用Mac,换了新公司使用的电脑是windows,网上粗略的看了一下Jekyll的安装.简略的实现了一遍 首先安装Ruby Ruby安装文件下载地址 下载对应版本,我的电脑是64位的下载64位的版本 ...
- 原子操作(atomic operation)
深入分析Volatile的实现原理 引言 在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共 ...
- java求最大公约数(分解质因数)
下面是四种用java语言编程实现的求最大公约数的方法: package gcd; import java.util.ArrayList; import java.util.List; public c ...
- iOS6和iOS7适应代码(6) —— NSLocalizedString
我们的应用程序都需要国际化,字符串的重要组成部分.一般来说.我们是通过一个string资源文件来达到这个目的,我们需要支持多国语言,有多少次把这个文档本地化.需要使用的代码NSLocalizedStr ...
- ASP.NET MVC:Razor 引入命名空间
原文:ASP.NET MVC:Razor 引入命名空间 页面中引用 c# @using MvcApplication83.Models @using MvcApplication83.Common 行 ...
- js:深闭包(范围:上)
/** * 范围封锁 */ fn1(); //fn1 您可以运行,没有报错,对于由function func_name()这样的写法来定义的函数,永远都会被最先初始化. function fn1( ...
- (Chrome42)Lodop总计页面提示“未安装”要么“请升级”可能的原因和解决方案
Chrome42版本号之后,支持NP态,要手工打开,方法例如以下: 在谷歌浏览器地址栏输入: chrome://flags/#enable-npapi 然后找到"启用NPAPI"地 ...
- jQuery遍历table中间tr td并获得td价值
jQuery遍历table中间tr td并获得td中间值 $(function(){ $("#tableId tr").find("td").each(func ...
- PostgreSQL 9.3 Streaming Replication 状态监控
postgresql是使用Streaming Replication来实现热备份的,热备份的作用如下: 灾难恢复 高可用性 负载均衡,当你使用Streaming Replication来实现热备份(h ...
- Spring中的事务传播行为
Spring在TransactionDefinition接口中定义了7种类型的事务传播行为,它们规定了事务方法是怎样传播的. PROPAGATION_REQUIRED(最经常使用!):支持当前事务,假 ...