网络编程(C语言)
套接字 socket
本地 IPC、网络通信
网络
计算机网络:有线或无线的链路连接多个设备(节点)进行数据通信或设备控制。
拓扑结构
- 星型网:局域网,
- 总线型:几个局域网连接
- 环型(令牌):城域网
- 复合型:综合
设备(节点)
- 计算机
- 交换机 switch、集线器 hub:连接计算机组成局域网
- 路由器 rounter:连接网络与网络
- 网关:过滤、拦截
- 中继器
- ...
介质
- 有线:双绞线(8)、电话线(4)、同轴电缆、光纤、电力
- 无线:移动网络、WIFI、蓝牙、红外、NFC、卫星...
MAC 物理地址
设备的序列号,是唯一的
以太网: 网线网络:C4-FF-99-D3-D2-22 WIFI:
IP 地址
IP 是逻辑编号,接入网络的设备,由 DHCP 自动的分配一个 IP 也可以手动绑定一个逻辑地址
MAC IP
C4-FF-99-D3-D2-22 10.162.238.35 C4-FF-99-D3-D2-22 10.162.238.36
IPv4: 32 2^32 42亿 IPv6: 128 2^128
SIM 序列号 手机号码
A类地址
范围:1.0.0.0 ~ 126.255.255.255(首字节0开头,二进制形式为0xxxxxxx)12
子网掩码:255.0.0.0(/8)13
用途:大型网络(如政府机构、跨国企业),每个网络支持约1677万台主机23B类地址
范围:128.0.0.0 ~ 191.255.255.255(首字节10开头,二进制形式为10xxxxxx)12
子网掩码:255.255.0.0(/16)13
用途:中型网络(如大学、中型企业),每个网络支持约6.5万台主机C类地址
范围:192.0.0.0 ~ 223.255.255.255(首字节110开头,二进制形式为110xxxxx)12
子网掩码:255.255.255.0(/24)13
用途:小型网络(如家庭、办公室),每个网络支持约254台主机D类地址
范围:224.0.0.0 ~ 239.255.255.255(首字节1110开头,用于组播)12
用途:一对多通信(如视频会议、流媒体分发),无子网掩码E类地址
范围:240.0.0.0 ~ 255.255.255.254(首字节1111开头,保留地址)12
用途:实验或未来使用,不可用于常规通信
126.255.255.255
11111111.00000000.00000000.00000000
126.0.0.0
126.2.25.55 255.0.0.0
126.0.0.0
端口号
一台机器中有多个程序, 每个程序还有还多进程或线程(浏览器每个标签页独立、迅雷)
操作系统中虚拟的接口,标记网络通信中进行数据收发的位置
一个程序可以占用多个端口
系统:2^16 65536个端口 前 1024 个端口保留,22 ssh, 80 www,
IP 计算机 端口 数据读取的位置:取件码
通信协议
通信双方预先约定的一套规则
ISO 国际标准化组织定义 OSI 开放系统互联参考模型
七层 意义:分层实现、一层之和相邻的层交互
- 应用层
- 表示层
- 会话层
- 传输层
- 网络层
- 数据链路层
- 物理层:电气接口相关的规范
主要贡献者:文森瑟夫、bill joy(vim、TCP/IP、Sun) TCP/IP 协议族
- 应用层:会话层、表示层、应用层 HTTP,HTTPS,SSH,SSL,POP,SMTP,自定义
- 传输层:TCP、UDP
- 网络层:IP
- 物理层:物理层、数据链路层
协议
- TCP/IP
*
- IPX
- NetBIOS
- apple
- xxx
参考资料
- 图解 TCP/IP 协议
- TCP/IP 详解(三卷)
知识点
- 三次握手
- 四次挥手
- 滑动窗口
- 掉包处理
- ...
socket 编程
套接字类型
- TCP 传输控制协议
- UDP 用户数据报协议
特征 | TCP | UDP |
---|---|---|
连接 | 是 | 否 |
有序 | 是 | 否 |
可靠 | 是 | 否 |
数据大小 | 不限 | 受限 |
开销 | 高 | 低 |
编程模型 | 客户服务器 | 对等 |
// server.c
// 服务端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>#define NAME "tserver"int main(int argc, char const *argv[])
{// 删除unlink(NAME);// 1. 创建套接字:域,协议类型int fd = socket(AF_UNIX, SOCK_STREAM, 0);// 创建一个地址// 本地通信struct sockaddr_un addr;addr.sun_family = AF_UNIX;strcpy(addr.sun_path, NAME);// 网络通信地址// struct sockaddr_in addr2;// addr2.sin_family = AF_INET;// addr2.sin_port = 9000;// 2. 套接字绑定地址bind(fd, (struct sockaddr *)&addr, sizeof(addr));// 3. 准备连接的队列listen(fd, 4096);printf("服务启动...\n");while (1){// 新套接字,连接客户端int c_fd;// 客户端的地址信息struct sockaddr_un c_addr;c_addr.sun_family = AF_UNIX;int size = sizeof(c_addr);// 接收连接c_fd = accept(fd, (struct sockaddr *)&c_addr, &size);// 读写char buf[128];memset(buf, '\0', 128);read(c_fd, buf, 128);printf("收到:%s\n", buf);char msg[] = "bye TCP!";write(c_fd, msg, sizeof(msg));// 关闭客户端close(c_fd);}return 0;
}
// client
// 客户端
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>#define NAME "tserver"int main(int argc, char const *argv[])
{// 1. 创建套接字int fd = socket(AF_LOCAL, SOCK_STREAM, 0);struct sockaddr_un addr;addr.sun_family = AF_UNIX;strcpy(addr.sun_path, NAME);// 2. 连接int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr));if (r == -1){perror("客户端连接失败\n");return EXIT_FAILURE;}// 3. 读写printf("请输入:");char buf[128];fgets(buf, 128, stdin);// 发送write(fd, buf, 128);// 接收memset(buf, '\0', 128);read(fd, buf, 128);printf("收到:%s\n", buf);// 4. 关闭连接close(fd);return 0;
}