关闭监听socket后,accpet仍然一直阻塞?

小竹z 2016-04-11 12:35:47
RT.在linux下开发服务器程序,我使用单独一个线程来accpet,当程序关闭时,主线程会调用各类对象析构函数,析构函数里调用close(fd),fd是监听socket描述符,但是accpet仍然阻塞,线程不能结束。我试了试shutdown(fd,SHUT_RDWR),accept就可以返回,为什么呢?
刚才测试下epoll_wait也有同样的问题。当在析构函数里调用close(efd),epoll_wait仍然没有唤醒还是继续阻塞,efd是epoll句柄,如果正确使用呢?
...全文
190 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
小竹z 2016-04-13
  • 打赏
  • 举报
回复
引用 4 楼 zgxyz2010 的回复:
[quote=引用 3 楼 lgbxyz 的回复:] 不会啊,close之后,accept会返回错误 “Bad file descriptor”

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <pthread.h>

#include <signal.h>


class Server {
public:
	Server(void);
	~Server(void);
	void server_create(const char* ip = "0.0.0.0", const char* port = "80");
	void server_start(void);
	void server_stop(void);

private:
	static int listen_fd;

};

int Server::listen_fd = 0;

Server::Server(void)
{

}
Server::~Server(void)
{
	if (listen_fd > 0)
	{
		close(listen_fd);
	}
}

void Server::server_create(const char* ip, const char* port)
{
	int opt = 1;
	struct sockaddr_in serv;
	
	listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	
	memset(&serv, 0x00, sizeof(serv));
	serv.sin_family = AF_INET;
	inet_aton(ip, &serv.sin_addr);
	serv.sin_port = htons(atoi(port));
	bind(listen_fd, (struct sockaddr *)&serv, sizeof(serv));
	
	listen(listen_fd, 5);
}


void* routine(void* arg)
{
	int apt_fd;
	struct sockaddr_in client;
	socklen_t len = sizeof(client);
	int listen_fd = *(int*)arg;
	char buf[4096] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHELLO";
	
	free(arg);

	while (1)
	{
		apt_fd = accept(listen_fd, (struct sockaddr*)&client, &len);
		if (apt_fd < 0)
		{
			perror("accept");
			break;
		}
		recv(apt_fd, buf + 1024, 4096 - 1024, 0);
		send(apt_fd, buf, strlen(buf), 0);
		close(apt_fd);
	}
	
	return NULL;
}
void Server::server_start(void)
{
	pthread_t pid;
	int *arg = (int*)malloc(sizeof(int));
	*arg = listen_fd;
	
	pthread_create(&pid, NULL, routine, arg);
	pthread_join(pid, NULL);
}


void Server::server_stop(void)
{
	close(listen_fd);
}

void sighandler(int arg)
{
	Server srv;
	srv.server_stop();
}

void* routine_server(void* arg)
{
	Server srv;

	srv.server_create();
	srv.server_start();
	
	return NULL;
}

int main(void)
{
	pthread_t pid;
	signal(SIGINT, sighandler);
	
	pthread_create(&pid, NULL, routine_server, NULL);
	pthread_join(pid, NULL);
	
	return 0
[/qu 也不行额,我把你代码测试了下,ctrl+c之后,程序卡死,没有输出也没有退出,说明accept没有返回。
改为: void Server::server_stop(void) { shutdown(listen_fd,SHUT_RDWR); } 就可以退出了,ctrl+c,我的是centos7 64位操作系统
小竹z 2016-04-13
  • 打赏
  • 举报
回复
centos 7 64位
小竹z 2016-04-13
  • 打赏
  • 举报
回复
[quote=引用 3 楼 lgbxyz 的回复:] 不会啊,close之后,accept会返回错误 “Bad file descriptor”

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <pthread.h>

#include <signal.h>


class Server {
public:
	Server(void);
	~Server(void);
	void server_create(const char* ip = "0.0.0.0", const char* port = "80");
	void server_start(void);
	void server_stop(void);

private:
	static int listen_fd;

};

int Server::listen_fd = 0;

Server::Server(void)
{

}
Server::~Server(void)
{
	if (listen_fd > 0)
	{
		close(listen_fd);
	}
}

void Server::server_create(const char* ip, const char* port)
{
	int opt = 1;
	struct sockaddr_in serv;
	
	listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	
	memset(&serv, 0x00, sizeof(serv));
	serv.sin_family = AF_INET;
	inet_aton(ip, &serv.sin_addr);
	serv.sin_port = htons(atoi(port));
	bind(listen_fd, (struct sockaddr *)&serv, sizeof(serv));
	
	listen(listen_fd, 5);
}


void* routine(void* arg)
{
	int apt_fd;
	struct sockaddr_in client;
	socklen_t len = sizeof(client);
	int listen_fd = *(int*)arg;
	char buf[4096] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHELLO";
	
	free(arg);

	while (1)
	{
		apt_fd = accept(listen_fd, (struct sockaddr*)&client, &len);
		if (apt_fd < 0)
		{
			perror("accept");
			break;
		}
		recv(apt_fd, buf + 1024, 4096 - 1024, 0);
		send(apt_fd, buf, strlen(buf), 0);
		close(apt_fd);
	}
	
	return NULL;
}
void Server::server_start(void)
{
	pthread_t pid;
	int *arg = (int*)malloc(sizeof(int));
	*arg = listen_fd;
	
	pthread_create(&pid, NULL, routine, arg);
	pthread_join(pid, NULL);
}


void Server::server_stop(void)
{
	close(listen_fd);
}

void sighandler(int arg)
{
	Server srv;
	srv.server_stop();
}

void* routine_server(void* arg)
{
	Server srv;

	srv.server_create();
	srv.server_start();
	
	return NULL;
}

int main(void)
{
	pthread_t pid;
	signal(SIGINT, sighandler);
	
	pthread_create(&pid, NULL, routine_server, NULL);
	pthread_join(pid, NULL);
	
	return 0
[/qu 也不行额,我把你代码测试了下,ctrl+c之后,程序卡死,没有输出也没有退出,说明accept没有返回。
LubinLew 2016-04-12
  • 打赏
  • 举报
回复
不会啊,close之后,accept会返回错误 “Bad file descriptor”

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <pthread.h>

#include <signal.h>


class Server {
public:
	Server(void);
	~Server(void);
	void server_create(const char* ip = "0.0.0.0", const char* port = "80");
	void server_start(void);
	void server_stop(void);

private:
	static int listen_fd;

};

int Server::listen_fd = 0;

Server::Server(void)
{

}
Server::~Server(void)
{
	if (listen_fd > 0)
	{
		close(listen_fd);
	}
}

void Server::server_create(const char* ip, const char* port)
{
	int opt = 1;
	struct sockaddr_in serv;
	
	listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	
	memset(&serv, 0x00, sizeof(serv));
	serv.sin_family = AF_INET;
	inet_aton(ip, &serv.sin_addr);
	serv.sin_port = htons(atoi(port));
	bind(listen_fd, (struct sockaddr *)&serv, sizeof(serv));
	
	listen(listen_fd, 5);
}


void* routine(void* arg)
{
	int apt_fd;
	struct sockaddr_in client;
	socklen_t len = sizeof(client);
	int listen_fd = *(int*)arg;
	char buf[4096] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHELLO";
	
	free(arg);

	while (1)
	{
		apt_fd = accept(listen_fd, (struct sockaddr*)&client, &len);
		if (apt_fd < 0)
		{
			perror("accept");
			break;
		}
		recv(apt_fd, buf + 1024, 4096 - 1024, 0);
		send(apt_fd, buf, strlen(buf), 0);
		close(apt_fd);
	}
	
	return NULL;
}
void Server::server_start(void)
{
	pthread_t pid;
	int *arg = (int*)malloc(sizeof(int));
	*arg = listen_fd;
	
	pthread_create(&pid, NULL, routine, arg);
	pthread_join(pid, NULL);
}


void Server::server_stop(void)
{
	close(listen_fd);
}

void sighandler(int arg)
{
	Server srv;
	srv.server_stop();
}

void* routine_server(void* arg)
{
	Server srv;

	srv.server_create();
	srv.server_start();
	
	return NULL;
}

int main(void)
{
	pthread_t pid;
	signal(SIGINT, sighandler);
	
	pthread_create(&pid, NULL, routine_server, NULL);
	pthread_join(pid, NULL);
	
	return 0
Benson凡 2016-04-12
  • 打赏
  • 举报
回复
进程没有全部关闭,在后台还在运行。我记得好像有个一段时间延时
Wenxy1 2016-04-11
  • 打赏
  • 举报
回复
使用阻塞式socket,设置accept超时,即可解决线程同步问题。

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧