使用信号中断主线程
Using a signal to interrupt the main thread
我正在用 C 编写一个 server/client TCP 并发程序。每次客户端连接时,服务器的主线程都会创建一个新线程来处理该客户端。之后,主线程回到accept(),并一直卡住,直到另一个客户端连接。
但是,我希望客户端能够关闭服务器。为此,我假设我必须使用信号。我该如何解决这个问题。我对信号很陌生。我不知道如何向特定线程发送信号,也不知道如何在此处使用它们。
我希望客户端写入“..”并关闭服务器。
有什么想法吗?
谢谢
虽然我理解你的问题,但让我困惑的是,你在哪里使用这样的服务器?。不管怎样,希望大家用好这个服务器。
#include <signal.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
void sigfunc(int signo)
{
_exit(0); // safe to call in signal handler since it is async-signal-safe func
}
struct client_data {
int clifd;
pthread_t ptid;
};
void* client_func(void* _cli_data)
{
struct client_data* cli_data = (struct client_data*) _cli_data;
char buf[100];
for( ; ; ) {
int rd_status = read(cli_data->clifd, buf, sizeof(buf) - 1);
if (rd_status <= 0)
break;
buf[rd_status] = '[=10=]';
printf("%s", buf);
fflush(stdout);
}
close(cli_data->clifd);
pthread_kill(cli_data->ptid, SIGRTMIN);
return NULL;
}
int main()
{
/* Setup a Listening server */
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(8008);
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (bind(sockfd, (struct sockaddr*) &servaddr, sizeof(struct sockaddr_in)) != 0)
exit(1);
listen(sockfd, 5);
/* Setup signal handler, use SIGRTMIN as sync signal */
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
act.sa_handler = sigfunc;
sigaction(SIGRTMIN, &act, NULL);
/* Loop and listen for connections */
int addr_len;
for ( ; ; ) {
struct client_data cli_data;
cli_data.ptid = pthread_self();
addr_len = sizeof(struct sockaddr_in);
cli_data.clifd = accept(sockfd, (struct sockaddr*) &servaddr, &addr_len);
if (cli_data.clifd < 0)
continue;
pthread_t tid;
pthread_create(&tid, NULL, client_func, &cli_data);
}
}
航站楼 Session:
服务器
$ gcc SO.c -lpthread
$ ./a.out
Hi to the server
Bye to the server
$
客户
$ netstat -l | grep 8008
tcp 0 0 0.0.0.0:8008 0.0.0.0:* LISTEN
$ nc 127.0.0.1 8008
Hi to the server
Bye to the server
^C
$
代码有注释,大家可以看一下。正如@MartinJames 所说,您不需要在绝对不必要的情况下终止线程,您最好依赖 OS 例程。由于我们以异步方式处理信号,因此在信号处理程序中只能调用少数函数(async-signal-safe 个函数); _exit()
就是其中之一。
我正在用 C 编写一个 server/client TCP 并发程序。每次客户端连接时,服务器的主线程都会创建一个新线程来处理该客户端。之后,主线程回到accept(),并一直卡住,直到另一个客户端连接。
但是,我希望客户端能够关闭服务器。为此,我假设我必须使用信号。我该如何解决这个问题。我对信号很陌生。我不知道如何向特定线程发送信号,也不知道如何在此处使用它们。
我希望客户端写入“..”并关闭服务器。
有什么想法吗?
谢谢
虽然我理解你的问题,但让我困惑的是,你在哪里使用这样的服务器?。不管怎样,希望大家用好这个服务器。
#include <signal.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
void sigfunc(int signo)
{
_exit(0); // safe to call in signal handler since it is async-signal-safe func
}
struct client_data {
int clifd;
pthread_t ptid;
};
void* client_func(void* _cli_data)
{
struct client_data* cli_data = (struct client_data*) _cli_data;
char buf[100];
for( ; ; ) {
int rd_status = read(cli_data->clifd, buf, sizeof(buf) - 1);
if (rd_status <= 0)
break;
buf[rd_status] = '[=10=]';
printf("%s", buf);
fflush(stdout);
}
close(cli_data->clifd);
pthread_kill(cli_data->ptid, SIGRTMIN);
return NULL;
}
int main()
{
/* Setup a Listening server */
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(8008);
int sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (bind(sockfd, (struct sockaddr*) &servaddr, sizeof(struct sockaddr_in)) != 0)
exit(1);
listen(sockfd, 5);
/* Setup signal handler, use SIGRTMIN as sync signal */
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
act.sa_handler = sigfunc;
sigaction(SIGRTMIN, &act, NULL);
/* Loop and listen for connections */
int addr_len;
for ( ; ; ) {
struct client_data cli_data;
cli_data.ptid = pthread_self();
addr_len = sizeof(struct sockaddr_in);
cli_data.clifd = accept(sockfd, (struct sockaddr*) &servaddr, &addr_len);
if (cli_data.clifd < 0)
continue;
pthread_t tid;
pthread_create(&tid, NULL, client_func, &cli_data);
}
}
航站楼 Session:
服务器
$ gcc SO.c -lpthread
$ ./a.out
Hi to the server
Bye to the server
$
客户
$ netstat -l | grep 8008
tcp 0 0 0.0.0.0:8008 0.0.0.0:* LISTEN
$ nc 127.0.0.1 8008
Hi to the server
Bye to the server
^C
$
代码有注释,大家可以看一下。正如@MartinJames 所说,您不需要在绝对不必要的情况下终止线程,您最好依赖 OS 例程。由于我们以异步方式处理信号,因此在信号处理程序中只能调用少数函数(async-signal-safe 个函数); _exit()
就是其中之一。