共计 2964 个字符,预计需要花费 8 分钟才能阅读完成。
问题:网络编程接口中一些参数的意义是什么?
sock = socket(PF_INET, SOCK_STREAM, 0);
socket 参数详解
int socket(int domain, int type, int protocal);
参数 | 意义 |
domain | 套接字中应用的协定族信息 |
type | 套接字数据传输类型信息 |
prorocol | 设施间通信应用的协定信息 |
socket() 中的 domain 参数(协定族)
- PF_INET → IPv4 互联网协议族
- PF_INET6 → IPv6 互联网协议族
- PF_LOCAL → 本地通信的协定族
- PF_PACKET → 底层数据收发协定
- PF_IPX → Novell 专用协定(互联网分组替换协定)
- …
留神:不同协定中的地址表现形式可能不同,网络编程时地址类型必须和协定类型匹配
socket() 中的 type 和 protocol 参数
-
type : 用于指定协定类型
- SOCK_STREAM : 流式数据(TCP)
- SOCK_UGRAM : 报文式数据(UDP)
-
protocol:用于指定协定族合乎类型的具体协定
- domain 和 type 简直能够惟一确定一种协定,因而,这个参数通常为 0
- 即:0 代表 domain 和 type 指定后的默认协定
对于端口号和 IP 地址
- 端口号是一个 2 字节数据(无符号)
- 0 – 1024 作为特定端口被预约义(调配给特定应用程序)
- IP 地址是一个 4 字节无符号地址族(可分为 5 类地址)
深刻解析 IP 地址
IP 地址分为 网络标识 和 主机标识 两局部
- 网络标识:标识网络主机(设施)所在的网络
- 主机标识:标识网络主机(设施)的具体地址
问题:一个 IP 地址就 4 个字节,那么如何辨别网络标识和主机标识呢?
- IP 地址 和 子网掩码 配合应用辨别 网络标识 和 主机标识
- 子网掩码的表现形式也是一个 4 字节的整型数(无符号)
- 子网掩码用于从 IP 地址中提取 网络标识(& 操作)
深刻了解子网掩码
设:子网掩码为 M.N.P.Q,则子网可用 IP 地址数量 n = (256 - M) * (256 - N) * (256 - P) * (256 - Q)
例:IP 地址 211.99.34.33,掩码 255.255.2555.248,因而:211.99.34.33 所在子网有 8 个 IP 地址
所在子网地址:211.99.34.32
播送地址:211.99.34.39
6 个可调配地址:211.99.34.33 ... 211.99.34.38
注:子网地址即为网络标识
ip 地址 211.99.34.33,掩码 255.255.225.248
可知 211.99.34.33 所在子网有 8 个 IP 地址,且 8 = 2^3(二的三次方),所以 Y = 32 - 3 = 29
可示意为 211.99.34.33 / 29【简写模式】
注:29 为 32 位子网掩码的高位
算一算
IP 地址 192.168.3.44,掩码 255.255.255.0
问:子网地址是什么?播送地址是什么?可用地址有多少?简洁表示法是什么?答:子网地址:192.168.3.44
播送地址:192.168.3.255
可用地址:254 [256 - 0(子网地址) - 255(播送地址)]
简洁示意:192.168.3.44 / 24
非凡的地址
- 0.0.0.0 / 0 – 保留,罕用于代表“缺省网络”
- 127.0.0.0 / 8 – 回环地址,罕用于本地软件会送测试
- 255.255.255.255 / 32 – 播送地址
网络编程中的地址类型
int sock = 0;
struct sockaddr_in addr = {0};
sock = socket(PF_INET, SOCK_STREAM, 0); // Protocol Family,协定族
if (sock == -1) {pritnf("socket error\n");
return;
}
addr.sin_family = AF_INET; // Address Family,地址族
addr.sin_addr.s_addr = inet_addr("192.168.3.241");
addr.sin_addr.port = htons(8899);
if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {printf("connect error\n");
return -1;
}
问:(struct sockaddr*)&addr
的强制类型转换不会出问题吗?
地址数据类型解析
- struct sockaddr 可了解为顶层地址类型父类,其与子类的内存布局雷同
connect()
依据addr.sin_family
来判断是哪一种地址类型并进行相应解析
IP 地址相干函数
#include <arpa/inet.h>
函数原型 | 性能形容 |
in_addr_t inet_addr(const char* strptr); | 将 IP 字符串转换为合乎网络字节序的整数 |
int inet_aton(const char *cp, struct_addr *inp); | 将 IP 字符串转换为合乎网络字节序的整数,胜利返回 1,失败返回 0 |
char *inet_ntoa(struct in_addr in) | 将合乎网络字节序的整数地址转换为字符串模式 |
编程试验:地址函数试验
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <malloc.h>
int main()
{unsigned int addr = inet_addr("1.2.3.4");
struct in_addr addr1 = {0x09080706};
struct in_addr addr2 = {0x05040302};
char *s1 = inet_ntoa(addr1);
char *s1_s = strcpy(malloc(32), s1);
char *s2 = inet_ntoa(addr2);
char *s2_s = strcpy(malloc(32), s2);
printf("addr = %x\n", addr);
printf("addr1 = %x\n", addr1.s_addr);
printf("addr2 = %x\n", addr2.s_addr);
printf("s1 = %s\n", s1);
printf("s2 = %s\n", s2); // 留神这里!!printf("s1 == s2 : %d\n", s1 == s2); // 留神这里!!printf("s1_s = %s\n", s1_s);
printf("s2_s = %s\n", s2_s);
printf("s1_s == s2_s : %d\n", s1_s == s2_s);
if (inet_aton("D.T.Software", &addr1)) { // 留神这里!!printf("addr1 = %x\n", addr1.s_addr);
}
free(s1_s);
free(s2_s);
return 0;
}
输入
addr = 4030201
addr1 = 9080706
addr2 = 5040302
s1 = 2.3.4.5
s2 = 2.3.4.5 // 留神,转换后果被笼罩!!s1 == s2 : 1 // 两次为同一个地址!!s1_s = 6.7.8.9
s2_s = 2.3.4.5
s1_s == s2_s : 0
遗留的问题:如何加强服务端能力,同时反对多个客户端?什么是多播?什么是播送?
正文完