今天学习了一下UNIX socket编程第五章节5.1-5.7的内容-TCP回射server-client程序,这篇文章的目的主要是记录一些实验截图,加强记忆。
服务器代码:
#include <unp.h>
void
str_echo(int sockfd)
{
ssize_t n;
char buf[MAXLINE];
again:
while ((n = read(sockfd, buf, MAXLINE)) > 0)
Writen(sockfd, buf, n);
if (n < 0 && errno == EINTR)
goto again;
else if (n < 0)
err_sys("str_echo: read error");
}
int
main(int argc, char **argv)
{
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6001);
Bind(listenfd, (SA *)&servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; ) {
clilen = sizeof(cliaddr);
connfd = Accept(listenfd, (SA*)&cliaddr, &clilen);
if ((childpid = fork()) == 0) {
Close(listenfd);
str_echo(connfd);
exit(0);
}
Close(connfd);
}
}
客户端代码:
#include "unp.h"
void
str_cli(FILE *fp, int sockfd)
{
char sendline[MAXLINE], recvline[MAXLINE];
while (Fgets(sendline, MAXLINE, fp)) {
Writen (sockfd, sendline, strlen(sendline));
if (Readline(sockfd, recvline, MAXLINE) == 0 )
err_quit("str_cli:serv terminated prematurely");
Fputs(recvline, stdout);
}
}
int
main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
if (argc != 2) {
err_quit("usage:tcpcli <IPaddress>");
}
sockfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(6001);
Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
Connect(sockfd, (SA *)&servaddr, sizeof(servaddr));
str_cli(stdin, sockfd);
exit(0);
}
1.正常启动:

我们可以看到途中圈红的就是需要关注的一些信息:
PID和PPID的关系:子进程的PPID是父进程的PID,我们就可以看出PID为22030的进程是PID为21540进程的子进程.
STAT列的含义如下:
D 不可中断的休眠。通常是IO。
R 运行。正在运行或者在运行队列中等待。
S 休眠。在等待某个事件,信号。
T 停止。进程接收到信息SIGSTOP,SIGSTP,SIGTIN,SIGTOU信号。
W paging,在2.6之后不用。
X 死掉的进程,不应该出现。
Z 僵死进程。
通常还会跟随如下字母表示更详细的状态。
< 高优先级
N 低优先级
L 有pages在内存中locked。用于实时或者自定义IO。
s 进程领导者,其有子进程。
l 多线程
+ 位于前台进程组。
还有一些其他不常见的状态,遇到再添加说明。
WCHAN含义:
就上图的服务器而言:
Linux在进程阻塞于accept或connect时,输出wait_for_connect(书中是这么写的,但是这边是inet_csk_accept,应该是阻塞在accept);
Linux在进程阻塞于套接字输入或输出时,输出sk_wait_data;
就上图的客户端而言:
Linux在进程阻塞于客户端I/O时,输出n_tty_read;
正常终止:

这边可以看到客户端状态已经进入TIME_WAIT。
这边还是四次挥手的一个过程:
客户TCP发送一个FIN字节给服务器,服务器则以一个ACK响应,到这一步服务器套接字就处于CLOSE_WAIT状态,客户端套接字则处于FIN_WAIT_2状态。这是TCP连接终止序列的前半部分。
后半部分则是在服务器子程序在接收到来自客户端的FIN分节,他就会关闭已连接的套接字,这时会引发TCP连接终止的最后两个分节:一个从服务器发往客户端的FIN分节和一个从客户端发往服务器的ACK分节。至此,连接全部终止,客户端状态则进入TIME_WAIT
状态。
借鉴文章:(18条消息) ps命令中STAT列表达的含义_枫竹梦的博客-CSDN博客_ps stat
(18条消息) 23-tcp协议——TIME_WAIT状态和FIN_WAIT2状态_songly_的博客-CSDN博客_fin_wait
浙公网安备 33010602011771号