今天看tcp/ip卷1,看到了2msl等待状态那里,就想知道是不是linux和书上写的一样,如果在客户端有连接的情况下,我快速的重启服务两遍,服务是重启不起来的。(感觉实际上不是这样的,所以就做了一个测试)
服务端代码:
-
#include <stdlib.h>
-
#include <stdio.h>
-
#include <string.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <sys/epoll.h>
-
-
int port = 9112;
-
int MAX_EVENTS = 10;
-
-
int main() {
-
int sockfd;
-
sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
struct sockaddr_in servaddr, cliaddr;
-
memset(&servaddr, \'\\0\', sizeof(struct sockaddr_in));
-
servaddr.sin_family = AF_INET;
-
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
-
servaddr.sin_port = htons(port);
-
bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr));
-
listen(sockfd, SOMAXCONN);
-
int cliaddr_len = sizeof(cliaddr);
-
char *buf = malloc(256);
-
-
int nfds;
-
struct epoll_event ev, events[MAX_EVENTS];
-
ev.events = EPOLLIN;
-
ev.data.fd = sockfd;
-
int epollfd = epoll_create(10);
-
if (epollfd == -1) {
-
perror(\"epoll_create\");
-
exit(0);
-
}
-
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) {
-
perror(\"epoll_ctl: listen_sock\");
-
exit(0);
-
}
-
-
int i;
-
int newfd_mark;
-
int num;
-
while(1) {
-
memset(buf, \'\\0\', 256);
-
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
-
if (nfds == -1) {
-
perror(\"epoll_pwait\");
-
exit(0);
-
}
-
for (i=0; i<nfds; ++i) {
-
int clifd;
-
if (events[i].data.fd == sockfd) { // 有新的连接
-
clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
-
newfd_mark = 1;
-
}
-
else {
-
clifd = events[i].data.fd;
-
newfd_mark = 0;
-
}
-
num = read(clifd, buf, 256);
-
printf(\"111 num is %dbbbb\\n\", num);
-
if (num <= 0) { // 对方关闭了连接,将close这个sock,将这个sock对应的event从eventlist中去掉
-
printf(\"in num < 0\\n\");
-
if (epoll_ctl(epollfd, EPOLL_CTL_DEL, clifd, NULL) == -1) {
-
perror(\"epoll_ctl: listen_sock\");
-
}
-
printf(\"close fd %d\\n\", clifd);
-
//close(clifd);
-
shutdown(clifd, SHUT_RDWR);
-
continue;
-
}
-
-
printf(\"num is %d\\n\", num);
-
write(clifd, buf, 256);
-
printf(\"recv is %s\\n\", buf);
-
if (newfd_mark == 1) { // 新来的连接,把这个连接增加进eventlist
-
struct epoll_event ev;
-
ev.events = EPOLLIN;
-
ev.data.fd = clifd;
-
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, clifd, &ev) == -1) {
-
perror(\"epoll_ctl: listen_sock\");
-
}
-
}
-
}
-
}
-
free(buf);
-
close(sockfd);
-
return 0;
-
}
客户端代码
-
#include <stdlib.h>
-
#include <stdio.h>
-
#include <string.h>
-
#include <sys/socket.h>
-
#include <netinet/in.h>
-
#include <arpa/inet.h>
-
-
-
-
int main() {
-
int sockfd;
-
sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
struct sockaddr_in servaddr, selfaddr;
-
memset(&servaddr, \'\\0\', sizeof(struct sockaddr_in));
-
servaddr.sin_family = AF_INET;
-
servaddr.sin_port = htons(9112);
-
inet_pton(AF_INET, \"127.0.0.1\", &servaddr.sin_addr);
-
// 客户端自己帮顶端口
-
selfaddr.sin_family = AF_INET;
-
selfaddr.sin_port = htons(12306);
-
selfaddr.sin_addr.s_addr = htons(INADDR_ANY);
-
bind(sockfd, (const struct sockaddr *)&selfaddr, sizeof(selfaddr));
-
-
connect(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr));
-
char *content = \"hello world\\n\";
-
char *recvbuf = (char *)malloc(256);
-
memset(recvbuf, \'\\0\', 256);
-
write(sockfd, content, strlen(content));
-
read(sockfd, recvbuf, 256);
-
printf(\"000 %s\", recvbuf);
-
sleep(10);
-
memset(recvbuf, \'\\0\', 256);
-
write(sockfd, content, strlen(content));
-
read(sockfd, recvbuf, 256);
-
printf(\"%s\", recvbuf);
-
close(sockfd);
-
return 0;
-
}
测试的时候首先测试客户端主动关闭,测试客户端程序里面没有sleep那行
第一次运行test_c,然后sudo netstat -npa | grep 9112,可以看到
tcp 0 0 0.0.0.0:9112 0.0.0.0:* LISTEN 10344/./test_s
tcp 0 0 127.0.0.1:12306 127.0.0.1:9112 TIME_WAIT -
这说明已经在TIME_WAIT状态了,并且过了一段时间之后第二行TIME_WAIT没有了,说明过了2msl了。
如果连续运行两次test_c,发现第二次运行的时候,客户端的端口变了
tcp 0 0 0.0.0.0:9112 0.0.0.0:* LISTEN 10344/./test_s
tcp 0 0 127.0.0.1:59667 127.0.0.1:9112 TIME_WAIT -
tcp 0 0 127.0.0.1:12306 127.0.0.1:9112 TIME_WAIT -
说明linux不是像tcp/ip书里说的那样,没法运行,而是强制换了一个端口,即使bind了一个端口也没用
然后测试服务端主动关闭
如果在客户端的两次发送数据之间加上sleep(10),同时在这期间,将服务端ctrl+c掉,然后在重新启动,结果发现还能启动起来,但是如果用netstat看一下会发现
tcp 0 0 0.0.0.0:56321 0.0.0.0:* LISTEN 10781/./test_s
说明服务端端口号也会变,不管bind和listen的是哪个
ps:在测试服务端主动关闭的时候在把服务端ctrl+c之后,sleep之后的write的信息还能还能被服务端再给回显回来,不知道是为什么。
阅读(7003) | 评论(1) | 转发(0) |