网络间通信
发布时间:2026/8/25 15:47:40 作者:尧图编辑部 阅读量:1,286

一、进程间通信方式回顾1. 同一主机单机内部通信传统方式管道有名管道FIFO无名管道pipe信号signalIPC方式System V IPC共享内存share memory信号量semaphore消息队列message queue2. 不同主机网络通信Socket套接字用于不同主机之间的进程通信二、网络通信核心问题举例说明西安的 PCQQ_A←→ 成都的 PCQQ_B需要解决两个核心问题找到对方的电脑 → 需要IP 地址找到电脑中的进程QQ 程序→ 需要端口号Port三、OSI 七层网络模型OSI 七层模型理想模型尚未完全实现四、TCP/IP 模型实际工业标准五、Linux 系统中的网络层次对应关系如何通过编程实现网络通信[用户空间] ←→ 应用层应用程序 ------------------------------------ Socket 接口套接字 [内核空间] ←→ 传输层TCP/UDP 网络层IP 链路层网卡驱动 物理层硬件如何实现应用层代码通过Socket 函数接口六、Socket 编程基础Socket 是什么socket()是一个函数接口用来使用网络功能Linux 一切皆文件的思想socket 也是一种特殊的文件专门用来进行网络通信网络编程两大协议基于 TCP 协议基于 UDP 协议七、TCP 协议TCPTransmit Control Protocol传输控制协议类比打电话TCP 三大特点面向连接通信前必须建立好逻辑通路可靠传输四个无无丢失无失序无差错无重复字节流有好处也有问题TCP 三次握手建立连接客户端Client 服务器Server 1. ----- SYN我要通话----→ 2. ←--- SYNACK嗯我知道了你可以---- 3. ----- ACK嗯好的----→TCP 应用场合对可靠性要求较高的场合QQ、微信等软件的登录过程八、UDP 协议UDPUser Datagram Protocol用户数据报协议类比生活中的广播UDP 三大特点无连接数据发送时不需要建立连接不保证可靠传输数据报一包一包发送UDP 应用场合小数据量但对速度要求较高QQ 即时文本信息语音通话实时性要求较高的场合广播、组播电子教室VNC 广播无线网络传输九、网络编程模型三种模型C/S 模型Client/Server客户端/服务器模型—重点本次学习的B/S 模型Browser/Server浏览器/服务器模型P2P 模型Peer to Peer点对点模型正在使用 P2P 加速技术TCP C/S 通信模型重点两个阶段建立连接三次握手通信数据收发十、TCP 客户端/服务器编程流程客户端流程主动方1. socket() // 买个手机 2. bind() // 可选的一般不绑定 3. connect() // 拨打电话 4. read() / write() 5. close()服务器端流程被动方1. socket() // 买个手机 2. bind() // 插 SIM 卡绑定服务器地址信息 3. listen() // 待机监听是否有客户端连接 4. accept() // 接听电话处理客户端连接完成连接建立 5. read() / write() 6. close()十一、Socket 函数1.socket()函数#include sys/types.h #include sys/socket.h int socket(int domain, int type, int protocol);功能创建通信的一端参数domain地址族AF_UNIX, AF_LOCAL本地通信AF_INETIPv4 互联网协议AF_INET6IPv6 互联网协议type套接字类型SOCK_STREAM流式套接字TCP提供有序、可靠、双向、基于连接的字节流支持带外数据传输SOCK_DGRAM数据报套接字UDP支持数据报无连接、不可靠、固定最大长度protocol协议类型TCP 协议UDP 协议填 0 表示使用默认协议返回值成功返回 socket 的文件描述符失败返回 -1并设置 errno2.connect()函数客户端#include sys/types.h #include sys/socket.h int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);功能发起连接请求拨打电话参数sockfd使用的 socket 文件描述符addr要通信的地址对于客户端就是服务器的 IP 端口addrlenaddr 参数地址的大小返回值成功0失败-1并设置 errno3. 地址结构struct sockaddr_instruct sockaddr_in { sa_family_t sin_family; // 地址族AF_INET in_port_t sin_port; // 端口号网络字节序 struct in_addr sin_addr; // IP 地址网络字节序 }; /* Internet address. */ struct in_addr { uint32_t s_addr; // IP 地址网络字节序 };十二、字节序Byte Order大端 vs 小端大端Big Endian高字节存放在低地址小端Little Endian低字节存放在低地址x86 架构网络字节序采用大端字节序字节序转换函数端口号转换htons()uint16_t htons(uint16_t hostshort);功能将主机字节序的端口号转换为网络字节序IP 地址转换inet_addr()in_addr_t inet_addr(const char *cp);功能将点分十进制字符串形式的 IP 地址如 192.168.1.1转换为网络字节序的 IP 地址IP 地址反向转换inet_ntoa()char *inet_ntoa(struct in_addr in);功能将网络字节序的 IP 地址转换为点分十进制字符串形式的 IP 地址十三、IP 地址详解IP 地址的本质在 IPv4 网络中IP 地址是32 位二进制数采用大端字节序网络字节序点分十进制表示法将 32 位二进制码划分为 4 个字节每个字节转换为十进制数字节之间用.分隔例如192.168.31.243二进制11000000.10101000.00011111.11110011IP 地址分类IPv4A 类B 类C 类D 类E 类子网掩码Subnet Mask作用用来区分网络号也可以获取主机号十四、端口号Port端口号的作用用来标识一个网络进程在网络中找到主机后IP通过端口号找到主机中的进程端口号的组成16 位数据2 字节范围0 ~ 65535端口号分类1 ~ 1023知名端口号Well-known Ports80HTTP23Telnet21FTP1024 ~ 50000系统注册端口Registered Ports≥ 50000动态端口Dynamic/Private Ports网络进程唯一标识IP 地址 端口号 网络中进程的唯一地址十五、服务器端其他函数4.bind()函数服务器#include sys/types.h #include sys/socket.h int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);功能给 socket 绑定一个名字地址信息参数sockfd要绑定的 socket 文件描述符addr绑定服务器自己的地址信息addrlen服务器地址的大小返回值成功0失败-1并设置 errno5.listen()函数服务器#include sys/types.h #include sys/socket.h int listen(int sockfd, int backlog);功能将 socket 设置为监听套接字被动套接字参数sockfd要设置的 socketbacklog表示等待队列的大小返回值成功0失败-1并设置 errno6.accept()函数服务器#include sys/types.h #include sys/socket.h int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);功能从 listen 的等待队列中提取第一个连接请求完成连接同时创建一个新的 socket表示已经连接好的 socket最终返回这个已连接好的 socket 的文件描述符参数sockfd监听套接字的文件描述符addr用来保存对端客户端的地址信息addrlen值结果参数必须初始化sizeof(客户端地址类型)返回值成功返回已连接好的 socket 的文件描述符失败返回 -1并设置 errno注意代码十六、客户端与服务器的 Socket 数量客户端只有1 个 socket服务器有2 个 socketa. 监听 socket用于接受连接b. 通信 socket用于数据收发十七、练习练习 1客户端输入信息服务器打印客户端client1. socket() 2. connect() 3. while(1) { fgets() // 从键盘获取输入 write(fd) // 发送给服务器 read(fd) // 接收服务器响应 } 4. close()服务器端server1. socket() 2. bind() 3. listen() 4. connfd accept() 5. 通信 while(1) { read(connfd, buf, ...) // 读取客户端数据 printf(%s, buf) // 打印输出 // 可选回显修改后的数据 char sbuf[1024]; sprintf(sbuf, server%s\n, buf); write(connfd, sbuf); } 6. close()练习 2点对点聊天多进程版本客户端client1. socket() 2. connect() 3. fork() if (pid 0) { // 父进程发送消息 } else if (pid 0) { // 子进程接收服务器消息 } 4. close()服务器端server1. socket() 2. bind() 3. listen() 4. connfd accept() 5. fork() if (pid 0) { // 父进程发送消息 } else if (pid 0) { // 子进程接收客户端消息 } 6. close()多任务分工任务1专门负责发送消息任务2专门负责接收消息练习 3点对点聊天多线程版本十八、总结关键函数列表函数用途使用方socket()创建套接字双方bind()绑定地址服务器listen()监听连接服务器accept()接受连接服务器connect()发起连接客户端read()/write()数据收发双方close()关闭连接双方