当前位置: 代码迷 >> 综合 >> accept() -- 从监听队列中取出连接
  详细解决方案

accept() -- 从监听队列中取出连接

热度:13   发布时间:2023-12-14 10:01:44.0

今天在《Linux高性能服务器编程》中看到:accept()函数是从监听队列中取出连接,于是自己使用书上的方法验证了一下,代码如下:

//accept_abnor_data.cpp#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>int main(int argc, char * argv[]) {if (argc <= 2) {printf("usage:%s ip_address port_number\n", argv[0]);return 1;}const char * ip = argv[1];int port = atoi(argv[2]);struct sockaddr_in address;bzero(&address, sizeof(address));address.sin_family = AF_INET;inet_pton(AF_INET, ip, &address.sin_addr);address.sin_port = htons(port);int sock = socket(PF_INET, SOCK_STREAM, 0);assert(sock >= 0);int ret = bind(sock, (struct sockaddr *)&address, sizeof(address));assert(ret != -1);ret = listen(sock, 5);assert(ret != -1);sleep(20); //睡眠20sstruct sockaddr_in client;socklen_t client_addrlength = sizeof(client);int connfd = accept(sock, (struct sockaddr *)&client, &client_addrlength);  //accept()是从监听队列中取出连接,不论连接状态如何if (connfd < 0) {printf("errno is: %d\n", errno);     }else {//接受成功打印客户端ip和端口号char remote[INET_ADDRSTRLEN];printf("connected with ip :%s and port :%d\n", inet_ntop(AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN), ntohs(client.sin_port));}return 0;
}

修改Makefile结果如下:

.PHONY:clean all
CC=gcc
GFLAGS=-Wall -g
BIN=accept_abnor_data
all:$(BIN)
%.0:%.c$(CC) $(GFLAGS) -c $< -o $@
clean:rm -f *.o $(BIN)

打开终端(1),执行下列命令:

make
./accept_abnor_data 192.168.1.104 12345

打开另一个终端(2),使用telnet命令进行登录:

telnet 192.168.1.104 12345

结果如下:
这里写图片描述
再打开一个终端终端,查看端口状态:

netstat -nt | grep 12345

查看到网络状态如下:
这里写图片描述
终端(1)中的./accept_abnor_data 192.168.1.104 12345命令执行20后,即睡眠结束,终端(1)上会打印出:

这里写图片描述
终端(2)上会打印出:
这里写图片描述
以上是客户端正常退出的结果,下面我们来看一下客户端异常退出的情况:
操作与上面不同的是,我们在终端使用telnet远程登录时(测试是在本地进行的),登录成功后,键入ctrl+],强制退出到telnet命令界面,再键入quit命令,结果如下:
这里写图片描述
客户端已经退出,此时的端口状态为:
这里写图片描述
客户端和服务器端端口状态分别为:FIN_WAIT2 、CLOSE_WAIT
此时,你能以为服务器端不会接受客户端的本次连接了,可等到服务器端睡眠20s后,仍能接受客户端的请求,并打印客户端的ip和端口号:
这里写图片描述

由此可见,accept()函数只是从监听队列中取出连接,并不关心连接处于何种状态,更不关心任何网络状况的变化,只要监听队列中有请求连接,服务器端就可以进行连接。

注:测试是在本地进行的,本地ip为192.168.1.104

参考:
《高性能服务器编程》

  相关解决方案