帯域外データを処理する単純なクライアントとサーバーを作成しました。クライアントは単一の帯域外データをサーバーに送信するだけで、サーバーは SIGURG を使用してこの単一バイトを処理します。サーバーは、無限ループで通常のトラフィックも処理する必要があります。コードには、期待どおりに動作しない競合状態があります。SIGURG ハンドラーでの recv() の呼び出しから「無効な引数」が返されることがあります。もう 1 つの質問は、accept を呼び出すときに SIGURG シグナルをブロックする必要があるということです。また、どちらが好ましいシナリオですか:
- accept を呼び出す前に、SIGURG ハンドラーをインストールし、リッスンしているソケットのソケット所有者を設定します。
- SIGURG ハンドラーをインストールし、accept を呼び出した後、接続されたソケットのソケット所有者を設定します。
- 上記のいずれでもない場合は、提案を書いてください。
私の最後の質問は、クライアントが帯域外データをすぐに送信するため、サーバーが SIGURG を受信する可能性はありますか? もしそうなら、「clifd」変数は、SIGURG ハンドラーで使用されたときに無効な値を持つ可能性があると思います。
クライアントのコード:
#include "myheader.h"
int main(int argc, char *argv[])
{
struct sockaddr_in saddr;
int sockfd;
const char c = 'a';
if (2 != argc)
{
fprintf(stderr, "Usage: %s ipaddr\n", argv[0]);
exit(EXIT_FAILURE);
}
if (-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
die("sockfd()");
(void)memset(&saddr, 0, sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
if (-1 == inet_pton(AF_INET, argv[1], &saddr.sin_addr))
die("inet_pton()");
if (-1 == connect(sockfd, (struct sockaddr*)&saddr, sizeof(saddr)))
die("connect()");
// if (-1 == send(sockfd, "HELLO\n", 6, 0))
// die("send()");
if (-1 == send(sockfd, &c, 1, MSG_OOB))
die("send()");
close(sockfd);
return 0;
}
サーバーのコード:
#include "myheader.h"
void sigurg_handler(int);
char oob;
int sockfd, clifd;
int main(void)
{
struct sockaddr_in myaddr;
char buf[BUFSIZ];
ssize_t nbytes;
sigset_t sset, oset;
sigemptyset(&sset);
sigaddset(&sset, SIGURG);
if (-1 == (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
die("socket()");
(void)memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons(PORT);
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
if (-1 == bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr)))
die("bind()");
if (-1 == listen(sockfd, BACKLOG))
die("listen()");
if (-1 == fcntl(sockfd, F_SETOWN, getpid()))
die("fcntl()");
if (SIG_ERR == signal(SIGURG, sigurg_handler))
die("signal()");
for (;;)
{
/* block SIGURG when accepting the connection */
// sigprocmask(SIG_SETMASK, &sset, &oset);
printf("bloking in accept()\n");
if (-1 == (clifd = accept(sockfd, NULL, NULL)))
die("accept()");
/* unblock SIGURG */
// sigprocmask(SIG_SETMASK, &oset, NULL);
printf("recv()ing normal data\n");
nbytes = recv(clifd, buf, sizeof(buf), 0);
buf[nbytes] = 0; /* null-terminate */
printf("%s", buf);
}
close(sockfd);
}
void
sigurg_handler(int signo)
{
char buff[100];
ssize_t nbytes;
printf("SIGURG received\n");
if (clifd != 0)
{
if (-1 == (nbytes = recv(clifd, buff, sizeof(buff) - 1, MSG_OOB)))
die("recv() in sigurg_handler()");
buff[nbytes] = 0;
printf("from sigurg_handler: received \"%s\"\n", buff);
}
else
{
printf("clifd = %d\n", clifd);
exit(1);
}
}
例:
> ./serv
bloking in accept() /* first client */
SIGURG received
from sigurg_handler: received "a"
recv()ing normal data
bloking in accept() /* second client */
SIGURG received
recv() in sigurg_handler(): Invalid argument
> ./serv /* third client */
bloking in accept()
SIGURG received
clifd = 0
>