gpt4 book ai didi

c - SIGIO从不开火

转载 作者:行者123 更新时间:2023-11-30 16:55:19 25 4
gpt4 key购买 nike

ioctl() 将套接字更改为异步模式。根据手册页上的定义,当套接字上可以进行 I/O 时,内核会发送 SIGIO。我已经使用测试客户端运行了这个,并且 I/O 正常(数据包到达源和目的地),那么为什么内核不调用 sigpoll?

澄清一下,问题在于,尽管已经建立了 SIGIO 信号并占用了套接字来发送信号 SIGIO,但没有信号触发,也没有迹象表明 sigpoll() 被调用。

我已经上传了发现此问题的代码,它最终将成为谈话的一些淡化版本。

talkish.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <setjmp.h>
#include <string.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/time.h>

#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/in.h>

#define MAX_BUF 1000
#define CHAR_BUF 50
#define BASEPORT "10000"

void error(const char *msg){
perror(msg);
exit(1);
}

typedef struct tuple{
char HN [MAX_BUF];
char PN [MAX_BUF];
}tuple;

tuple storeCMD( char input[]){
tuple ret;
char* token = strtok(input, " ");
if (token != NULL) strcpy( ret.HN, token);
else ret.HN[0] = 0;
token = strtok(NULL, " ");
if (token != NULL) strcpy( ret.PN, token);
else ret.PN[0] = 0;
return ret;
}

void sigpoll(int sig){
printf("Signal fired!\n");

//eventual rcvfrom and other things...
}

int main(int argc, char * argv[]){

if (argc != 2){
printf("Proper usage requires 2 arguments: $talkish port-number\n");
exit(1);
}
int sd;
struct sockaddr_storage client;
socklen_t clientLen;

struct addrinfo server, *res;
struct addrinfo *serverinfo;
char buffer [MAX_BUF];

memset(&server, 0, sizeof(server));
bzero((char *) &server, sizeof(server));

server.ai_family = AF_INET;
server.ai_socktype = SOCK_DGRAM;
server.ai_flags = AI_PASSIVE;

//initially we'll use information from user, but move to partner and partnerl
//once solid connection is established.
struct sockaddr_storage partner;
socklen_t partnerl;
//Bind to argv[1]
tuple execute;

getaddrinfo(NULL, argv[1], &server, &res);

sd = socket(res -> ai_family ,res -> ai_socktype, res -> ai_protocol);
if (sd < 0) error("ERROR on socket!");

int n = bind(sd, res -> ai_addr, res -> ai_addrlen);
if (n < 0) error("ERROR on Bind!");

int flag;
flag= 1;
fcntl(sd, F_SETOWN, getpid());
signal(SIGPOLL, sigpoll); //establish sigpoll to get udp packets
ioctl(sd, FIOASYNC, &flag);

//establish timer to allow wait and see
struct timeval timer;
timer.tv_sec = 7;

//while connecting

char message[CHAR_BUF];
bzero((char *) message, CHAR_BUF);
int connecting = 1;
while(connecting){
printf ("? ");
scanf(" %[^\n]", message);

if (strlen(message) == 0);
else if ( 0 == strcmp( message, "q")){
exit (0);
}
else {
execute = storeCMD(message);
if (execute.HN[0] == 0 || execute.PN[0] == 0) printf("| Input should match \"Hostname Portname\" to connect and \"q\" to quit \n");
else {

struct sockaddr_storage dest_server;
socklen_t dest_serverl;
struct addrinfo dest_hints, *dest_res;
struct in_addr dest_addr;

memset(&dest_hints, 0, sizeof(dest_hints));
dest_hints.ai_family = AF_INET;
dest_hints.ai_socktype = SOCK_DGRAM;
dest_hints.ai_flags = AI_PASSIVE;

if (getaddrinfo( execute.HN, execute.PN, &dest_hints, &dest_res) < 0) printf("| Input should match \"Hostname Portname\" to connect and \"q\" to quit \n");
else {

bzero((char *) buffer, MAX_BUF);
sprintf(buffer, "wannachat");

sendto(sd, buffer, MAX_BUF, 0, (struct sockaddr *) dest_res -> ai_addr, dest_res -> ai_addrlen );

if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer)) < 0) error("ERROR on setsockopt");

partnerl = sizeof(partner);
bzero((char *) &partner, partnerl);
bzero((char *) buffer, MAX_BUF);

if (recvfrom(sd, buffer, MAX_BUF, 0, (struct sockaddr *)&partner, &partnerl ) < 0) printf("| No response received from %s. \n", execute.HN);
else{
if ( 0 == strcmp( buffer, "OK")){
printf("| Connected to %s. \n", execute.HN);
//chat();
}else printf("| %s does not want to talk. \n", execute.HN);
}
}
}
}
}

close(sd);
return 0;
}

最佳答案

要接收 SIGIO 通知(对于套接字也是 SIGURG,例如:当接收 TCP URG 数据时),您需要告诉内核要通知谁,使用 fcntl(fd, F_SETOWN, pid) 。通常,正的 pid 值指的是一个进程,而负的 pid 值指的是一个进程组。

在 Linux 上,如果要将信号发送到特定线程,则需要使用 F_SETOWN_EX 。在其他系统上,您必须阻止其他线程上的信号。使用pthread_sigmask() .

关于c - SIGIO从不开火,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40334670/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com