타임아웃.. 예외없이 SELECT로 해결하시면 될듯합니다. 다만 CONNECT시 응답이 늦으면 완전히 블락이 걸리는 특성이 있으니 이전에 넌블락 모드로 설정하신후에 마지막에 이것을 해제해주시면 될듯합니다.
int status;
socket(); // 접속용 소켓 오픈
fcntl(); // 넌블락으로 셋
status = connect();
이부분에서 기종에 따라 리턴값이 달라집니다. 보통은 0보다 작으면서 PROGRESS메시지를 리턴하는데 이때 루프에 들어가 select 해주시면 됩니다.
while()
select(); 이부분은 쓰기검사를 하시고요.
connect();
대충 생각나는데로 해보았는데 저의 경험으로는 단지 리눅스용으로 하실거라면 이정도만 해도 잘 돌아 갑니다. 그런데 다른 기종에 포팅을 생각하시면 에러 리턴을 조금더 세밀하게 맞추셔야 할겁니다. 제가 LINUX/AIX/HPUX/SOLARIS 이렇게 맞추었는데 조금씩 다르더라구요.
시간이 되시면 모자익 소스를 한번 보시는게 어떠실런지요. 이거를 조금 수정하셔서 하시는게 좋을듯 싶습니다. 잠깐만요. 주소를 한번 찾아 보구요. 지금 찾았습니다.
PUBLIC int HTDoConnect (char *url, char *protocol, int default_port, int *s)
{
struct sockaddr_in soc_address;
struct sockaddr_in *sin = &soc_address;
int status;
/* Set up defaults: */
sin->sin_family = AF_INET;
sin->sin_port = htons(default_port);
/* Get node name and optional port number: */
{
char line[256];
char *p1 = HTParse(url, "", PARSE_HOST);
int status;
sprintf (line, "Looking up %s.", p1);
HTProgress (line);
status = HTParseInet(sin, p1);
if (status)
{
sprintf (line, "Unable to locate remote host %s.", p1);
HTProgress(line);
free (p1);
return HT_NO_DATA;
}
sprintf (line, "Making %s connection to %s.", protocol, p1);
HTProgress (line);
free (p1);
}
/* Now, let's get a socket set up from the server for the data: */
*s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#ifdef SOCKS
/* SOCKS can't yet deal with non-blocking connect request */
HTClearActiveIcon();
status = Rconnect(*s, (struct sockaddr*)&soc_address, sizeof(soc_address));
if ((status == 0) && (strcmp(protocol, "FTP") == 0))
SOCKS_ftpsrv.s_addr = soc_address.sin_addr.s_addr;
{
int intr;
intr = HTCheckActiveIcon(1);
if (intr)
{
if (TRACE)
fprintf (stderr, "*** INTERRUPTED in middle of connect.\n");
status = HT_INTERRUPTED;
errno = EINTR;
}
}
return status;
#else /* SOCKS not defined */
/*
* Make the socket non-blocking, so the connect can be canceled.
* This means that when we issue the connect we should NOT
* have to wait for the accept on the other end.
*/
{
int ret;
int val = 1;
char line[256];
ret = ioctl(*s, FIONBIO, &val);
if (ret == -1)
{
sprintf (line, "Could not make connection non-blocking.");
HTProgress(line);
}
}
HTClearActiveIcon();
/*
* Issue the connect. Since the server can't do an instantaneous accept
* and we are non-blocking, this will almost certainly return a negative
* status.
*/
status = connect(*s, (struct sockaddr*)&soc_address, sizeof(soc_address));
/*
* According to the Sun man page for connect:
* EINPROGRESS The socket is non-blocking and the con-
* nection cannot be completed immediately.
* It is possible to select(2) for comple-
* tion by selecting the socket for writ-
* ing.
* According to the Motorola SVR4 man page for connect:
* EAGAIN The socket is non-blocking and the con-
* nection cannot be completed immediately.
* It is possible to select for completion
* by selecting the socket for writing.
* However, this is only possible if the
* socket STREAMS module is the topmost
* module on the protocol stack with a
* write service procedure. This will be
* the normal case.
*/
#ifdef SVR4
if ((status < 0) && ((errno == EINPROGRESS)||(errno == EAGAIN)))
#else
if ((status < 0) && (errno == EINPROGRESS))
#endif /* SVR4 */
{
struct timeval timeout;
int ret;
ret = 0;
while (ret <= 0)
{
fd_set writefds;
int intr;
FD_ZERO(&writefds);
FD_SET(*s, &writefds);
/* linux (and some other os's, I think) clear timeout...
let's reset it every time. bjs */
timeout.tv_sec = 0;
timeout.tv_usec = 100000;
#ifdef __hpux
ret = select(FD_SETSIZE, NULL, (int *)&writefds, NULL, &timeout);
#else
ret = select(FD_SETSIZE, NULL, &writefds, NULL, &timeout);
#endif
/*
* Again according to the Sun and Motorola man pagse for connect:
* EALREADY The socket is non-blocking and a previ-
* ous connection attempt has not yet been
* completed.
* Thus if the errno is NOT EALREADY we have a real error, and
* should break out here and return that error.
* Otherwise if it is EALREADY keep on trying to complete the
* connection.
*/
if ((ret < 0)&&(errno != EALREADY))
{
status = ret;
break;
}
else if (ret > 0)
{
/*
* Extra check here for connection success, if we try to connect
* again, and get EISCONN, it means we have a successful
* connection.
*/
status = connect(*s, (struct sockaddr*)&soc_address,
sizeof(soc_address));
if ((status < 0)&&(errno == EISCONN))
{
status = 0;
}
break;
}
/*
* The select says we aren't ready yet.
* Try to connect again to make sure. If we don't get EALREADY
* or EISCONN, something has gone wrong. Break out and report it.
* For some reason SVR4 returns EAGAIN here instead of EALREADY,
* even though the man page says it should be EALREADY.
*/
else
{
status = connect(*s, (struct sockaddr*)&soc_address,
sizeof(soc_address));
#ifdef SVR4
if ((status < 0)&&(errno != EALREADY)&&(errno != EAGAIN)&&
(errno != EISCONN))
#else
if ((status < 0)&&(errno != EALREADY)&&(errno != EISCONN))
#endif /* SVR4 */
{
break;
}
}
intr = HTCheckActiveIcon(1);
if (intr)
{
if (TRACE)
fprintf (stderr, "*** INTERRUPTED in middle of connect.\n");
status = HT_INTERRUPTED;
errno = EINTR;
break;
}
}
}
/*
* Make the socket blocking again on good connect
*/
if (status >= 0)
{
int ret;
int val = 0;
char line[256];
ret = ioctl(*s, FIONBIO, &val);
if (ret == -1)
{
sprintf (line, "Could not restore socket to blocking.");
HTProgress(line);
}
}
/*
* Else the connect attempt failed or was interrupted.
* so close up the socket.
*/
else
{
close(*s);
}
return status;
#endif /* #ifdef SOCKS */
}
타임아웃.. 예외없이 SELECT로 해결하시면 될듯합니다. 다만 CONN
타임아웃.. 예외없이 SELECT로 해결하시면 될듯합니다. 다만 CONNECT시 응답이 늦으면 완전히 블락이 걸리는 특성이 있으니 이전에 넌블락 모드로 설정하신후에 마지막에 이것을 해제해주시면 될듯합니다.
int status;
socket(); // 접속용 소켓 오픈
fcntl(); // 넌블락으로 셋
status = connect();
이부분에서 기종에 따라 리턴값이 달라집니다. 보통은 0보다 작으면서 PROGRESS메시지를 리턴하는데 이때 루프에 들어가 select 해주시면 됩니다.
while()
select(); 이부분은 쓰기검사를 하시고요.
connect();
대충 생각나는데로 해보았는데 저의 경험으로는 단지 리눅스용으로 하실거라면 이정도만 해도 잘 돌아 갑니다. 그런데 다른 기종에 포팅을 생각하시면 에러 리턴을 조금더 세밀하게 맞추셔야 할겁니다. 제가 LINUX/AIX/HPUX/SOLARIS 이렇게 맞추었는데 조금씩 다르더라구요.
시간이 되시면 모자익 소스를 한번 보시는게 어떠실런지요. 이거를 조금 수정하셔서 하시는게 좋을듯 싶습니다. 잠깐만요. 주소를 한번 찾아 보구요. 지금 찾았습니다.
아랫부분을 조금 수정하셔서 사용하시는게 어떠실런지요.
http://archive.ncsa.uiuc.edu/SDG/Software/XMosaic/
답변감사합니다... 찾아보니 자료가 몇개 더 있더군요... ^^
찾아보니 자료가 더 있어 소스한개를 더 올립니다.
UNIX Networking programming 에 있는 소스입니다.
두가지 모두 테스트 해보았는데 모두잘되더군요...
alarm signal을 이용하시면 간단한데...[code:1]
alarm signal을 이용하시면 간단한데...
이렇게 하면 간단하게 구현할 수 있습니다~~~ 참조하세요~
[quote="은빛연어"]alarm signal을 이용하시면 간단한데..
아.. 이거 좋군요..;; recv()에 대해서도 똑같이 적용할 수 있나요? 있을거 같긴 한데.. 흠..
당근이졈~~ ^^*
당근이졈~~ ^^*
댓글 달기