对本地端口发起Http请求,为什么会有两次连接请求?
我用以下程序创建了一个服务端,监听本地8888端口:
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <unordered_map>
#include <fcntl.h>
using namespace std;
#define SERV_IP "0.0.0.0"
#define SERV_PORT 8888
#define MAX_CONN 1024
int main()
{
sockaddr_in servaddr, clitaddr;
unordered_map<int,sockaddr_in> fdmap; //文件描述符与其地址信息
epoll_event evt, evts[MAX_CONN];
char buf[1024]; //读缓冲区
int lfd; //监听描述符
int connfd; //连接描述符
int readycnt; //保存epoll_wait返回值
int epfd; //epoll描述符
socklen_t addr_len = sizeof(clitaddr);
if ((lfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
cout << "creat socket fault : " << strerror(errno) << endl;
return 0;
}
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
servaddr.sin_addr.s_addr = inet_addr(SERV_IP);
if (bind(lfd, (sockaddr *) &servaddr, sizeof(servaddr)) == -1)
{
cout << "bind fault : " << strerror(errno) << endl;
return 0;
}
if (listen(lfd, 128) == -1)
{
cout << "listen fault : " << strerror(errno) << endl;
return 0;
}
epfd = epoll_create(MAX_CONN); //创建epoll
if (epfd == -1)
{
cout << "epoll creat fault : " << strerror(errno) << endl;
return 0;
}
//lfd监听读事件
evt.events = EPOLLIN;
evt.data.fd = lfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, lfd, &evt) == -1) //将lfd加入epoll
{
cout << "epoll add error : " << strerror(errno) << endl;
return 0;
}
cout << "Init Success ! " << endl;
cout << "host ip : " << inet_ntoa(servaddr.sin_addr) << " port : " << ntohs(servaddr.sin_port) << endl;
cout << "Waiting for connections ... " << endl;
while (1)
{
readycnt = epoll_wait(epfd, evts, MAX_CONN, -1);
if (readycnt == -1)
{
cout << "epoll fault : " << strerror(errno) << endl;
return 0;
}
for (int i = 0; i < readycnt; i++) //遍历就绪描述符
{
if (evts[i].data.fd == lfd) //有新连接请求
{
connfd = accept(lfd, (sockaddr *) &clitaddr, &addr_len);
if (connfd == -1)
{
cout << "accept fault : " << strerror(errno) << endl;
continue;
}
cout << inet_ntoa(clitaddr.sin_addr) << ":" << ntohs(clitaddr.sin_port) << " connected ... " << endl;
fdmap[connfd] = clitaddr; //保存连接信息
fcntl(connfd,F_SETFL,O_NONBLOCK);
//添加新连接的监听
evt.events = EPOLLIN | EPOLLET;
evt.data.fd = connfd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &evt) == -1)
{
cout << "epoll add error : " << strerror(errno) << endl;
return 0;
}
}
else //有数据可读
{
int readcnt = 0;
while(1)
{
readcnt = read(evts[i].data.fd, buf, sizeof(buf));
if (readcnt == 0)
{
if (epoll_ctl(epfd, EPOLL_CTL_DEL, evts[i].data.fd, NULL) == -1)
{
cout << "epoll del error : " << strerror(errno) << endl;
return 0;
}
cout << inet_ntoa(fdmap[evts[i].data.fd] .sin_addr) << ":" << ntohs(fdmap[evts[i].data.fd] .sin_port) << " exit ... " << endl;
close(evts[i].data.fd);//关闭描述符
fdmap.erase(evts[i].data.fd);
}
else if(readcnt>0)
{
cout << "(From " << inet_ntoa(fdmap[evts[i].data.fd].sin_addr) << ":" << ntohs(fdmap[evts[i].data.fd].sin_port) << ")";
for (int j = 0; j < readcnt; j++)cout << buf[j];
cout << endl;
}
else
{
if(errno == EAGAIN) continue;
else break;
}
}
}
}
}
close(lfd);
return 0;
}
然后开启服务端,用浏览器访问127.0.0.1:8888,此时服务端信息以及抓包如下所示:
这里我有两个问题:
1.为什么会有两次连接进来?而且根据http请求报文的来源,真正有用的连接似乎只是46822?
2.从抓包结果我所理解的是,46822进行了三次握手,而46824只进行了一次握手,为什么服务端明明accept了但是没有SYN+ACK发回?
接下来我直接关闭了浏览器,此时服务端显示以及抓包如下所示:
根据我的理解,此时来自46822的连接,立刻发起四次挥手,服务端收到FIN后read返回0,然后服务端显示46822已经关闭了连接,
然后过了一会,才显示46824退出:
这里我就觉得很奇怪:为什么46824并没有像46822那样在浏览器关闭时就发起主动关闭,而是过了一会才关闭呢?
问题比较多,麻烦了!谢谢!!!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这种我也遇到过,不过有两种情况: