学习了计算机网络的相关知识,下面我们来从网络编程的角度验证一下网络实际交互的数据是什么。下面的程序用C语言在Linux环境下编写而成。
先准备一个服务器端程序,任何连上它的客户端,它都给返回服务器当前时间,然后立刻主动关闭连接。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#include "unp.h"
#include <time.h>
int main(int argc, char** argv) {
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[MAXLINE];
time_t ticks;
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(10241);
Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for (;;) {
connfd = Accept(listenfd, (SA*)NULL, NULL);
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(connfd, buff, strlen(buff));
Close(connfd);
}
}
|
客户端程序,连接服务器并打印获取的内容:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#include "unp.h"
int main(int argc, char** argv) {
int sockfd, n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
if (argc != 2)
err_quit("usage: a.out <IPaddress>");
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(10241); // daytime server
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
err_quit("inet_pton error for %s", argv[1]);
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");
while ((n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = 0;// null terminate
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
exit(0);
}
|
我们在Linux系统中编译得到两个可执行文件。开三个窗口,分别执行:
1
2
3
4
5
6
7
8
|
# 第一:启动Server
./UnpServer.out
# 第二:启动tcpdump监听,并将结果写入临时文件:
tcpdump -i lo -w time.tcpdump
# 第三:Client访问Server
./UnpClient.out 127.0.0.1
|
接下来将tcpdump监听的包日志文件 time.tcpdump下载到windows系统中。用包分析神器Wireshark分析,得到下面的结果:
如果我们直接看tcpdump的控制台日志,也是一样的:
啰嗦几句:
1
2
3
4
5
6
|
Flags表示包的状态标志
S=SYN:发起连接标志
P=PUSH:传送数据标志
F=FIN:关闭连接标志
.=ACK:表示确认或None
R=RST(RESET):重置连接
|
为什么主动关闭同时FIN+ACK
上面结果第6行,服务器端主动关闭连接。为什么发送的同时有FIN+ACK标志呢?
原因如下:TCP除了主动发起连接的第一个SYN包,ACK=0,其它所有TCP包都设置ACK= 1 标志位。《TCP/IP详解 卷1》中有这么一段话:
(完)