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));

后续我还在继续总结相关的实用知识点,大家敬请期待,如果我的文章对你有帮助,请帮忙留言转发点赞收藏哦。

全部评论
前几天刚看了这本书,通俗易懂很不错
2 回复 分享
发布于 2022-08-22 22:34 北京
可以写一下客户端与服务器的通信流程
点赞 回复 分享
发布于 2022-08-24 11:23 北京
点赞 回复 分享
发布于 2022-08-24 09:18 江西
点赞 回复 分享
发布于 2022-08-24 08:07 江苏
点赞 回复 分享
发布于 2022-08-23 20:23 北京
楼主多更新啊,好久不见
点赞 回复 分享
发布于 2022-08-22 22:35 北京

相关推荐

06-10 21:15
门头沟学院 Java
宁阿:好多这种没🧠的公司,他们估计都不知道毕业的人不能给安排实习岗
实习吐槽大会
点赞 评论 收藏
分享
评论
12
26
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务