《TCP/IP 网络编程》 阅读笔记(一)

110 阅读3分钟

创建套接字

#include<sys/socket.h>
int socket(int domain,int type, int protocol)
成功时返回文件描述符,失败时返回1

domain 套接字中使用的协议族 type 套接字数据传输类型信息 protocol 计算机间通信中使用的协议信息

协议族

PF_INET 对应的IPv4互联网协议族 image.png

套接字类型

套接字的类型指的是套接字的数据传输方式,通过socket函数的参数传递,只有这样才能决定创建的传输方式。

1. 面向连接的套接字(SOCK_STREAM)

特定与TCP相同 ,对应TCP连接 可靠的、按序传递的、基于字节的面向连接的数据传输方式的套接字

2. 面向消息的套接字(SOCK_DGRAM)

UDP 不可靠的,不按序传递的,以数据的高速传输为目的的套接字

协议的最终选择

大部分 第三个参数传递0,除非遇到下面这种情况 “同一协议族存在多个数据传输方式相同的协议”

表示 IPv4地址的结构体

struct sockaddr_in{
        sa_family_t         sin_family; // 地址族(address family)
        uint_t              sin_port;// 16位TCP/UDP端口号  TCP和UDP的端口号 相互独立
        struct in_addr      sin_addr; //32 位IP地址
        char                sin_zeor[8];// 不使用
}
该结构体中提到了另一个结构体 in_addr
struct in_addr{
    In_addr_in s_addr; //32位 IPv4地址
}
struct sockaddr{
    sa_family_t  sin_family;// 地址族
    char         sa_data[14]; //地址信息 
}

sockaddr_in 成员分析

image.png sin_port和sin_addr分别保存16位端口号和32位ip地址 sin_zero: 没有任何特殊含义,需要使sockaddr_in和sockaddr 结构体保持一致而插入的成员

网络字节序和主机字节序

网络字节序 : 大端序格式

htons 主机字节序转化为网络字节序

网络地址的初始化与分配

点分十进制的字符串转化为32位整数 inet_addr() 函数不仅可以把IP地址转化为32位整数型,而且可以检测无效的IP地址

# include<arpa/inet.h>
in_addr_t inet_addr(const char *string);
成功返回32位大端序整数型值,失败时返回INADDR_NONE

# include<arpa/inet.h>
// inet_aton 与inet_addr 功能上完全相同,只不过运用了 in_addr结构体 ,使用频率比较高
int inet_aton(const char *string,struct in_addr *addr);
 // 成功返回1(true),失败时返回0(false)

介绍一个与inet_aton函数正好相反的函数,此函数可以把网络字节序整数型IP地址转换为我们熟悉的字符串形式

#include<arpa/inet.h>
char *inet_ntoa(struct in_addr adr);
成功时返回转换的字符串地址值,失败时返回-1.

返回值类型为char类型的指针,说明字符串已经保存到内存空间中,但函数没有向程序员要求分配内存,而是在内部申请了了内存并保存了字符串。也就是说,调用完该函数后,应立即将字符串信息复制到其他内存空间。 如果再次调用inet_ntoa 函数,则有可能覆盖之前保存的字符串信息地址。

网络地址初始化

image.png

客户端地址 初始化

服务器端的准备工作通过bind函数完成,客户端则是通过connect函数完成 服务器端声明sockaddr_in结构体变量,初始化服务器端IP和套接字的端口号,然后调用bind函数。 客户端则声明sockaddr_in,初始化与之连接的服务器端IP和套接字的端口号,然后调用connect函数

INADDR_ANY

每次创建服务器端套接字都需要输入IP地址比较繁琐

image.png INADDR_ANY 自动获取服务器端的IP地址,若服务器有多个IP地址,那么只要端口号一致,就可以从不同的IP地址接收数据。

向套接字分配网络地址

#include<sys/socket.h> 
int bind(int sockfd, sturct sockaddr *myaddr, socklent_t addrlen);
// 成功返回0 ,失败返回-1
// sockfd 要分配地址信息 的套接字文件描述符
// myaddr 存有地址信息的结构体变量地址值。 
//addrlen 第二个结构体变量的长度