jackalwb 2020-01-01
1.Socket
1.1、socket是一个应用编程接口,是一种特殊的文件描述符(可对其执行IO操作,open、write、close)
1.2、socket代表网络编程的一种资源
1.3、socket的类型
流式套接字(SOCK_STREAM):唯一对应TCP
提供一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收,内置流量控制,避免数据流
淹没慢的接收方,数据流被看作字节流,无长度限制。
数据报套接字(SOCK_DGRAM):唯一对应UDP
提供无连接服务、数据包以独立数据包的形式发送,不提供无差错保证,数据可能丢失或重复,顺序发送,可能乱序接收。
原始套接字(SOCK_RAM):对应多个协议,发送穿透了传输层
可以对较低层协议如IP、ICMP直接访问
2、IP地址
2.1、IP地址是Internet中主机的1标识
— Internet中主机要与别的主机通信必须要有一个IP地址
— IP地址为32位(IPV4),或128位(IPV6)
— 每个数据包都必须携带目的IP地址和源IP地址,路由器依靠此信息为数据包选择路由
2.2、表示形式
—常用点分形式,如196.128.1.2
—32位整数
特殊IP地址:
—局域网IP:192.xxx.xxx.xxx 10.xxx.xxx.xxx
—广播IP:xxx.xxx.xxx.255 255.255.255.255(全网广播)
—组播IP:224.xxx.xxx.xxx ~ 239.xxx.xxx.xxx
3.端口号
为了区分一台主机接收到的数据包应交由哪个任务进行处理,使用端口号来区别
TCP 端口号与UDP端口号独立
端口号一般由INAN(Internet assigned numbers authority)管理
—众所周知端口:1--1023(1~255为众所周知端口,256~1023端口通常有UNIX系统占用)
—注册端口:1024~50000
—动态或私有端口: 50000~65535
网络里的通信是由 IP地址 + 端口号来决定的
4.字节序
4.1 主机字节序
字节序是指 整数 在内存中保存的顺序,是指不同的CPU访问内存中的多字节数据时,存在大小端问题。
(若CPU访问的是字符串,则不存在大小端问题。)
主机字节序(host-byte)指的是处理器存储数据的字节顺序。
eg: 0X 12345678 (0X 高位------低位)
最常见的有两种:
1.Little endian:将低序字节存储在起始地址——LE
2.Big endian:将高序字节存储在起始地址 ——BE
一般来说:
X86 / ARM : 小端模式
Powerpc / mips:大端模式
#include <stdio.h> #include <arpa/inet.h> int main(){ unsigned long a = 0x12345678; unsigned char *p = (unsigned char *)(&a); printf("主机字节序:%0x %0x %0x %0x\n", p[0], p[1], p[2], p[3]); unsigned long b = htonl(a); //将主机字节序转化成了网络字节序 p = (unsigned char *)(&b); printf("网络字节序:%0x %0x %0x %0x\n", p[0], p[1], p[2], p[3]); return 0; } ———————————————— 源程序链接:https://blog.csdn.net/msdnwolaile/article/details/50727653
验证主机大小端
4.2 网络字节序
网络字节序(network-byte)指的是网络编程时,存储数据的字节顺序。在网络编程时用到的IP地址和端口号都需要网络字节序。
与“主机字节序”相反,网络字节序将数据的重要部分保存在低地址,不重要的部分保存到高地址。
由于不同机器采用的字节序大小端可能不同,所以在传输数据的过程中,中间需要一个标准化的数据格式即网络字节序。
a的固有数据存储-------标准化--------转化成b的固有格式 ——> a的主机字节序----------网络字节序 ---------b的主机字节序
4.3 转换函数
可以通过一系列的函数实现主机字节序和网络字节序之间的转换。
函数中的h表示主机host,n表示网络networ,l表示长整形long,s表示短整形short。
/****主机字节序--->网络字节序****/ uing16_t htons(uint16_t short); uint32_t htonl(uint32_t hostlong); /****网络字节序---->主机字节序****/ uint16_t ntohs(uint16_t netshort); uint32_t ntohl(uint32_t netlong);
IP地址转换函数:
#include <arpa/inet.h> in_addr_t inet_addr(const char *cp); //net_addr的参数是一个:点分十进制字符串,返回的值为一个32位的二进制网络字节序的IPv4地址,不然的话就是:INADDR_NONE //特点: 1、仅适用于IPV4 // 2、出错返回-1 // 3、此函数不能用于255.255.255.255的转换 int inet_pton(int af, const char *src, void *dst) ; //参数: af---地址协议族(AF_INST和AF_INET6) // src--是一个指针(填写点分形式的IP地址,IPV4) // dst--转换的结果给dst //特点: 1、适应于IPV4和IPV6 // 2、能正确处理255.255.255.255的转换 // inet_ntop();
#include <stdio.h> #include <arpa/inet.h> int main() { struct in_addr ipaddr; unsigned long addr = inet_addr("192.168.1.100"); printf("addr = %u\n", ntohl(addr)); ipaddr.s_addr = addr; printf("%s\n", inet_ntoa(ipaddr)); return 0; } ———————————————— 源程序: https://blog.csdn.net/msdnwolaile/article/details/50727653
结果:
<1> 我一直以为自己很熟悉如何使用C/C++中的二进制文件,可今天测试的时候突然发现程序生成的二进制文件和文本文件一样。也就是说保存125这个数字还是会占用3个字节,而不是我想象中那样只占一个字节!