[mew-dist 25582] Re: SMTP error handling
KOIE Hidetaka ( 鯉江英隆 )
hide at example.com
2004年 10月 26日 (火) 16:08:44 JST
Message-Id: <20041026.152637.177324940.kazu at example.com>
Date: Tue, 26 Oct 2004 15:26:37 +0900 (JST)
From: Kazu Yamamoto (山本和彦) <kazu at example.com>
Subject: [mew-dist 25581] Re: SMTP error handling
| > selectで待つのはwsetだけでよいとおもいます。
|
| いえ、non-blocking の場合は、rset も必要なんですよ。そういうものらしい
| です。
FreeBSDのman pageですが
connectのEINPROGRESSの説明をみるとwritingで待てとあります。
| > 毎回timeoutを設定しなおした方がいいそうです。
|
| そうですか。
|
| > try回ループするかgettimeofdayで残り時間を算出するかは
| > 気合い次第です。
|
| 残り時間を算出するというのは、どうやるんですか?
| 残り時間って分りようがないような。
selectで指定するのがsleepする時間ではなくて
時刻を指定する仕様だったら簡単だったのですが..
| > connectが完了したとselectがいったときに
| > 成功したのか失敗したのかを
| > getsockopt(SOL_SOCKET,SO_ERROR)で取得した方がいいとおもいます。
| > ありがちなのがECONNREFUSEDです。
|
| ああ、やりますかねぇ。
きっと別のところでエラーが検出されるとおもうので
ここでがんばらなくてもよいという考えもあるとおもいます。
サンプルをつくってみたので参考になれば.
--
鯉江英隆 <hide at example.com>
-------------- next part --------------
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
main(int ac, char *const *av)
{
const char *node = av[1];
const char *port = av[2];
int err;
int s;
struct addrinfo hints;
struct addrinfo *res0;
struct addrinfo *res;
struct timeval now;
struct timeval deadline;
socklen_t optlen;
memset(&hints, 0, sizeof hints);
hints.ai_socktype = SOCK_STREAM;
err = getaddrinfo(node, port, &hints, &res0);
if (err) {
fprintf(stderr, "caonnot resolv: %s\n", gai_strerror(err));
exit(1);
}
for (res = res0; res; res = res->ai_next) {
char host[100], serv[100];
err = getnameinfo(res->ai_addr, res->ai_addrlen,
host, sizeof host,
serv, sizeof serv,
NI_NUMERICHOST|NI_NUMERICSERV);
if (err) {
fprintf(stderr, "getnameinfo: %s\n", gai_strerror(err));
exit(1);
}
printf("connecting %s %s\n", host, serv);
s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (s < 0) {
perror("socket");
exit(1);
}
if (fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL, 0)) < 0) {
perror("fcntl");
exit(1);
}
err = connect(s, res->ai_addr, res->ai_addrlen);
if (err == 0) {
printf("connected(1)\n");
goto done;
} else {
if (errno == EINPROGRESS)
break;
perror("connect(1)");
close(s);
}
}
freeaddrinfo(res0);
if (res == NULL) {
fprintf(stderr, "failure\n");
exit(1);
}
gettimeofday(&now, NULL);
deadline = now;
deadline.tv_sec += 2;
for (;;) {
struct timeval timeout;
fd_set wfds;
gettimeofday(&now, NULL);
timeout.tv_sec = deadline.tv_sec - now.tv_sec;
timeout.tv_usec = deadline.tv_usec - now.tv_usec;
if (timeout.tv_usec < 0) {
timeout.tv_sec--;
timeout.tv_usec += 1000000;
}
if (timeout.tv_sec < 0) {
fprintf(stderr, "timedout\n");
exit(1);
}
FD_ZERO(&wfds);
FD_SET(s, &wfds);
err = select(s+1, NULL, &wfds, NULL, &timeout);
if (err < 0 && errno != EINTR) {
perror("select");
exit(1);
}
if (FD_ISSET(s, &wfds))
break;
}
optlen = sizeof err;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &err, &optlen) < 0) {
perror("getsockopt");
exit(1);
}
if (err != 0) {
errno = err;
perror("connect:getsockopt");
exit(1);
}
printf("connected(2)\n");
done:
if (close(s) < 0) {
perror("close");
}
exit(0);
}
Mew-dist メーリングリストの案内