mirror of
https://github.com/riba2534/TCP-IP-NetworkNote.git
synced 2026-06-30 09:56:04 +08:00
docs: 全面校对全部章节文档与示例代码
通过多智能体工作流对 19 章笔记(README.md)与 96 个 .c 示例代码做深度 审查与对抗性验证,修复 317 处确认问题,涵盖: 技术正确性: - 修复缓冲区溢出:echo_mpserv.c / echo_storeserv.c 等的 read(buf, BUFSIZ) 改为 BUF_SIZE(buf 仅 30 字节,BUFSIZ 远大于此) - 修复 open() 缺少 mode 参数:low_open.c / fd_seri.c / desto.c 等 O_CREAT 调用补 0644(原导致 low_read 链路失败) - 修复 feof 循环 off-by-one:news_sender.c / echo_stdserv.c 改用 fgets 返回值判断 - 修复线程竞态:chat_server.c / webserv_linux.c 的 &clnt_sock 栈地址 传子线程改为 malloc 分配 + free - 修复索引混淆:char_EPLTserv.c 错用 clnt_sock 查找改为 ep_events[i].data.fd - 修复格式化符:thread4.c 的 sizeof 用 %d 改为 %zu - 修正习题答案:ch01 fd 序号、ch13 MSG_OOB 加粗项、ch09 Nagle 等 文档规范: - 统一术语:IPv4/IPv6、接收(receive)/连接(connection) - 修正错别字:occured→occurred、cooffee→coffee、Usgae→Usage、 eerror→error、proess→process 等 - 修复病句、补全习题答案解释 - GitHub 绝对 URL 改为相对路径,统一项目引用规范 - 同步根 README.md(前言 + 19 章合并) 另:重命名 ch10/remove_zomebie.c → remove_zombie.c(修正拼写) 所有 .c 文件经 gcc 编译验证通过(ch17 epoll 文件因 macOS 无 sys/epoll.h 跳过,已人工复核)。
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
本章代码,在[TCP-IP-NetworkNote](https://github.com/riba2534/TCP-IP-NetworkNote)中可以找到。
|
||||
|
||||
进程间通信,意味着两个不同的进程中可以交换数据
|
||||
进程间通信,意味着两个不同的进程之间可以交换数据。
|
||||
|
||||
### 11.1 进程间通信的基本概念
|
||||
|
||||
@@ -24,9 +24,9 @@ filedes[1]: 通过管道传输数据时使用的文件描述符,即管道入
|
||||
*/
|
||||
```
|
||||
|
||||
父进程调用函数时将创建管道,同时获取对应于出入口的文件描述符,此时父进程可以读写同一管道。但父进程的目的是与子进程进行数据交换,因此需要将入口或出口中的 1 个文件描述符传递给子进程。下面的例子是关于该函数的使用方法:
|
||||
父进程调用函数时将创建管道,同时获取对应于出入口的文件描述符,此时父进程可以读写同一管道。但父进程的目的是与子进程进行数据交换,因此需要通过 fork 让子进程继承这两个文件描述符,父子进程各自使用其中一端进行通信(实际编程中还应关闭各自不需要的一端)。下面的例子是关于该函数的使用方法:
|
||||
|
||||
- [pipe1.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch11/pipe1.c)
|
||||
- [pipe1.c](pipe1.c)
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
@@ -80,7 +80,7 @@ Who are you?
|
||||
|
||||
下面是双向通信的示例:
|
||||
|
||||
- [pipe2.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch11/pipe2.c)
|
||||
- [pipe2.c](pipe2.c)
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
@@ -129,7 +129,7 @@ Parent proc output: Who are you?
|
||||
Child proc output: Thank you for your message
|
||||
```
|
||||
|
||||
运行结果是正确的,但是如果注释掉代码中子进程里的 `sleep(2);`(第18行),就会出现问题,导致一直等待下去。因为数据进入管道后变成了无主数据。也就是通过 read 函数先读取数据的进程将得到数据,即使该进程将数据传到了管道。因为,注释掉 `sleep(2);` 会产生问题。子进程可能读回自己向管道发送的数据。结果父进程调用 read 函数后,无限期等待数据进入管道。
|
||||
运行结果是正确的,但是如果注释掉代码中子进程里的 `sleep(2);`(第18行),就会出现问题,导致一直等待下去。因为数据进入管道后变成了无主数据。也就是通过 read 函数先读取数据的进程将得到数据,即使该进程将数据传到了管道。此时子进程可能在父进程读取前就把自己写入的数据读回,导致父进程的 read 调用无限期阻塞,等待永远不会到来的数据。
|
||||
|
||||
当一个管道不满足需求时,就需要创建两个管道,各自负责不同的数据流动,过程如下图所示:
|
||||
|
||||
@@ -137,7 +137,7 @@ Child proc output: Thank you for your message
|
||||
|
||||
下面采用上述模型改进 `pipe2.c` 。
|
||||
|
||||
- [pipe3.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch11/pipe3.c)
|
||||
- [pipe3.c](pipe3.c)
|
||||
|
||||
```c
|
||||
#include <stdio.h>
|
||||
@@ -176,13 +176,13 @@ int main(int argc, char *argv[])
|
||||
|
||||
#### 11.2.1 保存消息的回声服务器
|
||||
|
||||
下面对第 10 章的 [echo_mpserv.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch10/echo_mpserv.c) 进行改进,添加一个功能:
|
||||
下面对第 10 章的 [echo_mpserv.c](../ch10/echo_mpserv.c) 进行改进,添加一个功能:
|
||||
|
||||
> 将回声客户端传输的字符串按序保存到文件中
|
||||
|
||||
实现该任务将创建一个新进程,从向客户端提供服务的进程读取字符串信息,下面是代码:
|
||||
|
||||
- [echo_storeserv.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch11/echo_storeserv.c)
|
||||
- [echo_storeserv.c](echo_storeserv.c)
|
||||
|
||||
编译运行:
|
||||
|
||||
@@ -191,13 +191,13 @@ gcc echo_storeserv.c -o serv
|
||||
./serv 9190
|
||||
```
|
||||
|
||||
此服务端配合第 10 章的客户端 [echo_mpclient.c](https://github.com/riba2534/TCP-IP-NetworkNote/blob/master/ch10/echo_mpclient.c) 使用,运行结果如下图:
|
||||
此服务端配合第 10 章的客户端 [echo_mpclient.c](../ch10/echo_mpclient.c) 使用,运行结果如下图:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
从图上可以看出,服务端已经生成了文件,把客户端的消息保存了下来,只保存了10次消息。
|
||||
从图上可以看出,服务端已经生成了文件,把客户端的消息保存了下来,只保存了 10 条消息(代码中固定循环读取 10 次)。
|
||||
|
||||
### 11.3 习题
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ int main(int argc, char *argv[])
|
||||
char buf[BUF_SIZE];
|
||||
if (argc != 2)
|
||||
{
|
||||
printf("Usgae : %s <port>\n", argv[0]);
|
||||
printf("Usage : %s <port>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
act.sa_handler = read_childproc; //防止僵尸进程
|
||||
@@ -48,7 +48,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *fp = fopen("echomsg.txt", "wt");
|
||||
char msgbuf[BUF_SIZE];
|
||||
int i, len;
|
||||
int len;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
len = read(fds[0], msgbuf, BUF_SIZE);
|
||||
@@ -69,7 +69,7 @@ int main(int argc, char *argv[])
|
||||
if (pid == 0) //子进程运行区域,此部分向客户端提供回声服务
|
||||
{
|
||||
close(serv_sock); //关闭服务器套接字,因为从父进程传递到了子进程
|
||||
while ((str_len = read(clnt_sock, buf, BUFSIZ)) != 0)
|
||||
while ((str_len = read(clnt_sock, buf, BUF_SIZE)) != 0)
|
||||
{
|
||||
write(clnt_sock, buf, str_len);
|
||||
write(fds[1], buf, str_len);
|
||||
|
||||
@@ -7,7 +7,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
int fds1[2], fds2[2];
|
||||
//const char* 以"\0"作为结束符
|
||||
char str1[] = "Do you like cooffee?";
|
||||
char str1[] = "Do you like coffee?";
|
||||
char str2[] = "I like coffee";
|
||||
char str3[] = "I like long legs";
|
||||
char * str_arr[] = {str1, str2, str3};
|
||||
|
||||
Reference in New Issue
Block a user