前言
网络通信一直都是所有的框架的基础
正文
一, TCP状态转换图
虚线:表示服务器的正常状态转换
实线:表示客户端的正常状态转换
应用:表示状态转换在应用进程发起操作时发生
接收:表示状态转换在接收到分节发生
发送:表示这个转换发生什么
二, TCP连接的分组交换
三,CLOSE_WAIT状态出现时机
有一端主动关闭socket链接, 在没有关闭socket链接的一端出现CLOSE_WAIT状态, 主动关闭socket的一端出现了FIN_WAIT_2状态, 在主动关闭socket一端没有收到被动关闭一端的响应会等待73秒后关闭, 而被动关闭有会有大量CLOSE_WAIT状态 的原因是没有关闭socket连接(网络连接无法释放)
1, 服务端有大量CLOSE_WAIT状态, 和客户端FIN_WAIT_2状态的使用
命令
tcpdump tcp port 80
抓包分析
2, 抓包分析结果
客户发送了FIN 服务端回一个ACK就介绍了
这是服务端的测试的代码测试的代码
#include "unp.h"
#include <time.h>
int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
int optval = 1;
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(SERV_PORT); /* daytime server */
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
//端口复用
//端口复用
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
for ( ; ; ) {
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
printf("connection from %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
//休息 了 就没有关闭服务端出现大量的CLOSE_WAIT状态
sleep(1000);
Write(connfd, buff, strlen(buff));
Close(connfd);
}
}
客户端的代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <strings.h>
#include <unistd.h>
#include <arpa/inet.h>
#define SERV_PORT 8888
#define SERV_IP "47.93.31.88"
#define MAXLINE 1024
int main(int argc, char **argv)
{
int sockfd, n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
printf("socket error\n");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT); /* daytime server */
if (inet_pton(AF_INET, SERV_IP, &servaddr.sin_addr) <= 0)
printf("inet_pton error for %s\n", SERV_IP);
if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
printf("connect error\n");
close(sockfd);
#if 0
while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
recvline[n] = 0; /* null terminate */
if (fputs(recvline, stdout) == EOF)
printf("fputs error\n");
}
if (n < 0)
printf("read error\n");
#endif
exit(0);
}
服务端的CLOSE_WAIT的状态
客户端FIN_WAIT_2状态
三, 解决上面的问题是 出现大量CLOSE_WAIT状态
原因是被动关闭的一端没有关闭socket连接 导致大量CLOSE_WAIT状态
现在就是关闭服务端socket连接
服务端的代码:
#include "unp.h"
#include <time.h>
int
main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
int optval = 1;
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(SERV_PORT); /* daytime server */
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
//端口复用
//端口复用
setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
//地址复用
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
for ( ; ; ) {
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
printf("connection from %s, port %d\n",
Inet_ntop(AF_INET, &cliaddr.sin_addr, buff, sizeof(buff)),
ntohs(cliaddr.sin_port));
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
//sleep(1000);
Write(connfd, buff, strlen(buff));
Close(connfd);
}
}
效果图: