TCPIP网络编程知识点总结
在我之前推荐的C++学习路线中,《TCPIP网络编程》这本书是学习C++网络编程的入门书籍,书中包含了linux和windows两个操作系统的网络编程,但我们更加常用的其实是在linux环境下。所以我整理了一些面试经常问到或者常见的代码结构体,供大家秋招复习使用。
IP是什么
IP是为收发网络数据而分配给计算机的值。
端口号是什么,他有什么特点
端口号并非赋予计算机的值,而是为区分程序中创建的套接字而分配给套接字的序号。
端口号就是在同一操作系统内为区分不同套接字而设置的,因此无法将1个端口号分配给不同的套接字。
端口号由16位构成,可分配端口号范围从0-65535。但0-1023是知名端口(Well-known PORT),一般分配给特定应用程序,所以应当分配范围之外的值。
端口不能重复,但TCP套接字和UDP套接字不会共用端口号,所以允许重复。
数据传输目标地址应该包含什么内容
应该同时包含ip地址和端口号,数据才会被传输到最终目的应用程序
sockaddr_in结构体是什么
sockaddr_in是保存IPV4地址信息的结构体
sockaddr_in结构体成员有哪些,各成员的具体含义
struct sockaddr_in { sa_family_t sin_family; //地址族(Address Family) uint16_t sin_port; //16位TCP/UDP端口号,以网络字节序保存 struct in_addr sin_addr; //32位IP地址,以网络字节序保存 char sin_zero[8]; //无特殊含义。只是结构体sockaddr_in的大小与sockeaddr结构体保持一致而插入的成员。 }; struct in_addr { in_addr_t s_addr; //32位IPv4地址 };
sockaddr结构体成员有哪些?
struct sockaddr { sa_family_t sin_family; // 地址族(Address Family) char sa_data[14]; // 地址信息 }; //sa_data保存的地址信息中需包含IP地址和端口号,剩余部分应填充0
为什么要用sockaddr_in,而不直接使用sockaddr,应该如何传递地址信息?
直接向sockaddr结构体填充端口号和IP地址信息会比较麻烦。
先填写sockaddr_in结构体,则将生成符合bind函数要求的字节流。
再转换为sockaddr型的结构体变量,最后传递给bind函数即可。
如何将地址信息传递给bind函数(代码实现)
struct sockaddr_in serv_addr; .... if(bind(serv_sock,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1) error_handling("bind() error"); ....
4字节整数型值1在内存空间的保存方式大端序和小端序
00000000 00000000 00000000 00000001 大端序
有些CPU以这种顺序保存到内存,另外一些CPU则以倒序保存。
00000001 00000000 00000000 00000000 小端序
大端序和小端序的概念
大端序(Big Endian): 高位字节存放到低位地址。
小端序(Little Endian): 高位字节存放到高位地址。
字节的高低位和地址的高低位
地址的前面是低位地址,后面是高位地址
字节的前面是高位字节,后面是低位字节
原封不动对应上去就是大端序,翻转过来就是小端序
网络字节序用的是什么方式
网络字节序统一使用大端序
字节序转换的函数和头文件
#include<arpa/inet.h> //头文件 unsigned short htons(unsigned short); unsigned short ntohs(unsigned short); unsigned long htonl(unsigned long); unsigned long ntohl(unsigned long); //h代表主机(host)字节序,n代表网络(network)字节序 //以s作为后缀的函数中,s代表2个字节short,因此用于端口号转换; //以l作为后缀的函数中,l代表4个字节,因此用于IP地址转换
数据在传输前需要转化为网络字节序吗?
不需要,这个过程是自动的,除了向sockaddr_in结构体填充数据外,其他情况无序考虑字节序问题
IP地址的网络字节序转换
//字符串形式IP地址转换为32位网络字节序整数并返回 int inet_aton(const char * string, struct in_addr * addr); // string 含需转换的IP地址信息的字符串地址值 // addr 将保存转换结果的in_addr结构体变量的地址值。 //把网络字节序整数型IP地址转换成点分十进制字符串形式 char * inet_ntoa(struct in_addr adr); //将函数名中的a改为p后可以支持IPV6网络
网络地址初始化(sockaddr_in结构体填充)
struct sockaddr_in addr; char* ser_ip = "211.217.168.13"; // 声明 IP 地址字符串 char* serv_port = "9190"; // 声明端口号字符串 memset(&addr, 0, sizeof(addr)); // 结构体变量addr的所有成员初始化为 0 addr.sin_family = AF_INET; // 指定地址族 addr.sin_addr.s_addr = inet_addr(serv_ip); // 基于字符串的IP地址初始化 addr.sin_port = htons(atoi(serv_port)); // 基于字符串的端口号初始化
服务端自动获取运行在服务端的ip地址
struct sockaddr_in addr; char * serv_port = "9190"; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(atoi(serv_port));
后续我还在继续总结相关的实用知识点,大家敬请期待,如果我的文章对你有帮助,请帮忙留言转发点赞收藏哦。