str_cli 和 str_echo 函数
需要先弄清楚 3.9 readn、writen 和 readline 函数
str_cli
void str_cli(FILE *fp, int sockfd) { char sendline[MAXLINE], recvline[MAXLINE]; while (Fgets(sendline, MAXLINE, fp) != NULL) { Writen(sockfd, sendline, strlen(sendline)); if (Readline(sockfd, recvline, MAXLINE) == 0) err_quit("str_cli: server terminated prematurely"); Fputs(recvline, stdout); } }
Fgets
char * fgets ( char * str, int num, FILE * stream );
Get string from stream
Reads characters from stream and stores them as a C string into str until (num-1) characters have been read or either a newline or the end-of-file is reached, whichever happens first.A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.
A terminating null character is automatically appended after the characters copied to str.
Notice that fgets is quite different from gets: not only fgets accepts a stream argument, but also allows to specify the maximum size of str and includes in the string any ending newline character.
Parameters
str
Pointer to an array of chars where the string read is copied.
num
Maximum number of characters to be copied into str (including the terminating null-character).
stream
Pointer to a FILE object that identifies an input stream.
stdin can be used as argument to read from the standard input.Return Value
On success, the function returns str.
If the end-of-file is encountered while attempting to read a character, the eof indicator is set (feof). If this happens before any characters could be read, the pointer returned is a null pointer (and the contents of str remain unchanged).
If a read error occurs, the error indicator (ferror) is set and a null pointer is also returned (but the contents pointed by str may have changed).
fgets 为 NULL 的情况:
1. read EOF 在有字节读取之前;
2. 发生错误;
char * Fgets(char *ptr, int n, FILE *stream) { char *rptr; if ( (rptr = fgets(ptr, n, stream)) == NULL && ferror(stream)) err_sys("fgets error"); return (rptr); }
包裹之后的 Fgets:如果发生错误,调用 err_sys,然后继续返回 rptr。
err_sys
The C library function void perror(const char *str) prints a descriptive error message to stderr. First the string str is printed, followed by a colon then a space.
void err_sys(const char* x) { perror(x); exit(1); }
为什么 Readline 返回 0 就说明对方关闭了连接呢?
read 当 EOF 时等于 0,因为 EOF 说明接下来没有数据可以读了。
In computing, end-of-file (commonly abbreviated EOF) is a condition in a computer operating system where no more data can be read from a data source.
str_echo
信号处理
Signal(SIGCHLD, sig_chld);
为什么 sig_chld 的 signo 参数没有用到?stat 又是什么?
#include "unp.h" void sig_chld(int signo) { pid_t pid; int stat; pid = wait(&stat); printf("child %d terminated\n", pid); return; }
5.12 服务器进程终止
不明白:(7) 中说明了,由于客户进程之前接收了 FIN,所以 readline 返回 0。为什么在小字中,还会读取到 RST?
习题
5.1 查看机器的 MSL
对于 MacOS 系统,通过 sysctl net.inet.tcp 系统 tcp 的各种设置。对于 msl,使用
$ sysctl net.inet.tcp | grep msl net.inet.tcp.msl: 15000
表示这台机器上的 msl 是 15000 毫秒,即 15秒。
然后,TIME_WAIT 的时间是 2*msl,即 30秒。
The duration that this endpoint remains in this state is twice the maximum segment lifetime (MSL), sometimes called 2MSL
from: 2.7 TIME_WAIT State
没弄懂。
为什么二进制会返回空字节?
5.4 杀掉服务器子进程之后,客户向服务器发送数据导致服务器TCP响应以一个RST。这个RST使得连接中断,并防止连接的服务器端经历TIME_WAIT状态。所以最后两个分节并不发送。
5.5 重启服务器进程后,新启动的服务器看不到之前某个 ESTABLISHED 状态的数据分节,所以同样返回 RST。
5.6
不明白 图5-15,左端数据链路与右端的不同。
5.8 数据格式不同,大端与小端。
参考答案:
总结
这章花了很多时间,
一是之前的函数没有弄懂,倒回去把之前的 readn, writen 弄懂了;
二是习题不会做,原因是么弄清概念,比如字节序大端和小端,32位和64位,函数修改之后编译;