文章目录
1,socket
- socket是一个应用编程的接口
- socket代表着网络编程的一种资源,是一种特殊的文件描述符 (everything in Unix is a file):对它执行IO的操作函数,比如,read(),write(),close()等操作函数
- 并不仅限于TCP/IP协议
- 面向连接 (Transmission Control Protocol - TCP/IP)
- 无连接 (User Datagram Protocol -UDP 和 Inter-network Packet Exchange - IPX)
1.1,socket的类型(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW)
- 流式套接字(SOCK_STREAM): 唯一对应着TCP
提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。 - 数据报套接字(SOCK_DGRAM): 唯一对应着UDP
提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或重复,顺序发送,可能乱序接收。 - 原始套接字(SOCK_RAW):(对应着多个协议,发送穿透了传输层)
可以对较低层次协议如IP、ICMP直接访问。
1.2,socket的位置
2,IP地址
- IP地址是Internet中主机的标识
·Internet中的主机要与别的机器通信必须具有一个IP地址
·IP地址为32位(IPv4)或者128位(IPv6)
·mobileIPV6: local IP(本地注册的IP),roam IP(漫游IP)
·每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包选择路由 - 表示形式:常用点分形式,如202.38.64.10,最后都会转换为一个32位的无符号整数。
- IP地址分类
- 子网掩码(跟局域网相关)
2.1,特殊IP地址:
-
局域网IP:
·192.XXX.XXX.XXX
·10.XXX.XXX.XXX -
广播IP:
·xx.xxx.xxx.255,
·255.255.255.255(全网广播,大部分企业都会限制) -
组播IP: (不能以255结尾,以224~239开头)
·224.XXX.XXX.XXX~239.xxx.xxx.xxx
3,端口号
-
为了区分一台主机接收到的数据包应该转交给哪个进程(哪个任务)来进行处理,使用端口号来区别
-
TCP端口号与UDP端口号独立
-
端口号是一个16位的数字(1-65535)
-
端口号一般由IANA (Internet Assigned Numbers Authority) 管理
·众所周知端口:1 ∼ 1023(1 ∼ 255之间为众所周知端口,256~1023端口通常由UNIX系统占用。FTP: 21,SSH: 22, HTTP:80, HTTPS:469)
·注册端口(保留端口):1024~49150
·动态或私有端口:49151~65535
保留端口: 1024-5000(不建议使用)
可以使用的:5000~65535 -
网络里面的通信是由 IP地址+端口号 来决定
4,字节序(大端序、小端序)
- 字节序是指不同的CPU访问内存中的多字节数据时候,存在大小端(字节序)问题,如CPU访问的是字符串,则不存在大小端问题
- 不同类型CPU的主机中,内存存储多字节整数序列有两种方法,称为主机字节序(HBO):
·小端序(little-endian) - 低序字节存储在低地址
将低字节存储在起始地址,称为“Little-Endian”字节序,Intel、AMD等采用的是这种方式(X86/ARM);
·大端序(big-endian)- 高序字节存储在低地址
将高字节存储在起始地址,称为“Big-Endian”字节序,由ARM、Motorola等所采用(powerpc/mips, ARM作为路由器时) - 网络中传输的数据必须按网络字节序,即大端字节序
- 在大部分PC机上,当应用进程将整数送入socket前,需要转化成网络字节序;当应用进程从socket取出整数后,要转化成小端字节序(原因?)
4.1,字节序(网络字节序(NBO和主机字节序HBO)
- 网络字节序(NBO - Network Byte Order)
·使用统一的字节顺序,避免兼容性问题 - 主机字节序(HBO - Host Byte Order)
·不同的机器HBO是不一样的,这与CPU的设计有关
·Motorola 68K系列、ARM系列,HBO与NBO是一致的
·Intel X86系列,HBO与NBO不一致 - Intel CPU采用小端序做主机序,网络中传输的数据必须按网络字节序,即大端字节序.因此,在大部分PC机上,当应用进程将整数送入socket前,需要转化成网络序;当应用进程从socket取出整数后,要转化成主机序
- 把给定系统所采用的字节序称为主机字节序。为了避免不同类别主机之间在数据交换时由于对于字节序的不同而导致的差错,引入了网络字节序。
4.2,字节序转换函数htonl()/htons()、ntohl()/ntohs()
- 主机字节序到网络字节序(host to network)
·u_long htonl (u_long hostlong);
·u_short htons (u_short short); - 网络字节序到主机字节序(network to host)
·u_long ntohl (u_long hostlong);
·u_short ntohs (u_short short);
5,IP地址的转换 inet_aton()、inet_addr()、inet_ntoa()、inet_pton()
inet_aton( )
#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);
- 将strptr所指的字符串转换成32位的网络字节序二进制值
inet_addr( )
int_addr_t inet_addr(const char *strptr);
- 功能同上,返回转换后的地址。
- strptr是以’\0’结尾的IPv4点分形式的IP地址字符串,该函数返回结果是32位的整数地址,如果字符串包含的不是合法的IP地址,则函数返回-1。(内部包含了字节序的转换,默认是网络字节序的模式)
- 特点:
- 仅适应于IPV4
- 当出错时,返回-1(在计算机内存储是补码的形式255.255.255.255)
- 此函数不能用于255.255.255.255的转换
例如:
struct in_addr addr;
addr.s_addr = inet_addr(" 192.168.1.100 ");
inet_ntoa( )
char *inet_ntoa(stuct in_addr inaddr);
- 将32位网络字节序二进制地址转换成点分十进制的字符串。
- inaddr是IPv4地址结构,函数返回一指向包含点分IP地址的静态存储区字符指针。如果错误则函数返回NULL
inet_pton()
int inet_pton(int af, const char *src, void *dst);
- 将IPV4/IPV6的地址转换成binary格式(内部包含了字节序的转换,默认是网络字节序的模式)
- 能正确的处理255.255.255.255的转换问题
- 参数:
- af: 地址协议族(AF_INET或AF_INET6)
- src:是一个指针(填写点分形式的IP地址[主要指IPV4])
- dst: 转换的结果给到dst
- 返回值
inet_pton() returns 1 on success (network address was successfully con‐verted). 0 is returned if src does not contain a character string representing a valid network address in the specified address family. If af does not contain a valid address family, -1 is returned and errno is set to EAFNOSUPPORT.
inet_ntop()
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);
- 将IPV4/IPV6的网络字节序地址,变成本地的字符串形式的IP地址
- 能正确的处理(-1)255.255.255.255的转换问题
- 参数:
- af: 地址协议族(AF_INET或AF_INET6)
- src:是一个指针(32位的网络字节序IP地址)
- dst: 转换的结果为点分形式的IP地址[主要指IPV4]
- size:src的长度
- 返回值
·On success, inet_ntop() returns a non-NULL pointer to dst.
·NULL is returned if there was an error, with errno set to indicate the error.