【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网络编程之套接字类型与协议设置
套接字与协议 如果相隔很远的两人要进行通话,必须先决定对话方式.如果一方使用电话,另一方也必须使用电话,而不是书信.可以说,电话就是两人对话的协议.协议是对话中使用的通信规则,扩展到计算机领域可整理为 ...
随机推荐
- axure7.0下载安装教程
做产品必需要有原型设计.我们公司称为做demo. demo你能够用ppt做,或者直接做图片.这样给甲方基本通只是. 也能够直接用html做,这样非常慢.尽管真正研发时或许能够复用: 平衡的方案,也是最 ...
- Cache
在选择的几点思考
Cache为缓解DB装有重要数据,下面经常使用memcached和redis要总结,促进技术的选择. 1 memcached (1) 有限支持的操作,持经常使用的set.get.delete和过期删 ...
- spring交易声明的几个传播特性
近期遇到了一个spring事务导致的问题,所以写了几个小程序了解了一下事务的传播特性,以下分别举样例分别看看事务的传播特性. 事务的几种传播特性 1. PROPAGATION_REQUIRED: 假设 ...
- 编程算法基地-2.1利用字符串API
2.1利用字符串API 字符串是Java类型最常用.并且是复合类型 串非常经常用于,其最佳API熟悉文档. 推断串中有没有反复的字符 String s ="abcdebxyz"; ...
- 浅析Java中的final关键字(转)
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下 ...
- MySQL学习系列2--MySQL执行计划分析EXPLAIN
原文:MySQL学习系列2--MySQL执行计划分析EXPLAIN 1.Explain语法 EXPLAIN SELECT …… 变体: EXPLAIN EXTENDED SELECT …… 将执行 ...
- MD5算法的原理与实现
***********************************************声明************************************************ 原创 ...
- Java数据结构与算法(20) - ch08树
树的主要算法有插入,查找,显示,遍历,删除,其中显示和删除略微复杂. package chap08.tree; import java.io.BufferedReader; import java.i ...
- 一个奇怪的注意事项TNS-12545 TNS-12560 TNS-00515
近来的reportDB无法从一开始就与系统收听,比较奇怪的现象. 由于server有听众的一个实例上正常启动,这是不是从开始监听器的实例手动启动是正常的.所以写下来未能找到离奇写的原因. 1.故障现象 ...
- Office——检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败
检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 8000401a 1.运行dcomcnfg.e ...