看了下这个库的源码,一个 FTP 的库,然后我看了下FtpConnect
方法的实现,看到用到了_REENTRANT
,不太清楚为什么要用这个宏,似乎是多线程有用
GLOBALDEF int FtpConnect(const char *host, netbuf **nControl)
{
int sControl;
struct sockaddr_in sin;
int on=1;
netbuf *ctrl;
char *lhost;
char *pnum;
memset(&sin,0,sizeof(sin));
sin.sin_family = AF_INET;
lhost = strdup(host);
pnum = strchr(lhost,':');
if (pnum == NULL)
pnum = "ftp";
else
*pnum++ = '\0';
if (isdigit(*pnum))
sin.sin_port = htons(atoi(pnum));
else
{
struct servent *pse;
#if _REENTRANT
struct servent se;
char tmpbuf[TMP_BUFSIZ];
int i;
if ( ( i = getservbyname_r(pnum,"tcp",&se,tmpbuf,TMP_BUFSIZ,&pse) ) != 0 )
{
errno = i;
if ( ftplib_debug )
perror("getservbyname_r");
free(lhost);
return 0;
}
#else
if ((pse = getservbyname(pnum,"tcp") ) == NULL )
{
if ( ftplib_debug )
perror("getservbyname");
free(lhost);
return 0;
}
#endif
sin.sin_port = pse->s_port;
}
if ((sin.sin_addr.s_addr = inet_addr(lhost)) == INADDR_NONE)
{
struct hostent *phe;
#ifdef _REENTRANT
struct hostent he;
char tmpbuf[TMP_BUFSIZ];
int i, herr;
if ( ( ( i = gethostbyname_r( lhost, &he, tmpbuf, TMP_BUFSIZ, &phe, &herr ) ) != 0 ) ||
( phe == NULL ) )
{
if ( ftplib_debug )
fprintf(stderr, "gethostbyname: %s\n", hstrerror(herr));
free(lhost);
return 0;
}
#else
if ((phe = gethostbyname(lhost)) == NULL)
{
if (ftplib_debug)
fprintf(stderr, "gethostbyname: %s\n", hstrerror(h_errno));
free(lhost);
return 0;
}
#endif
memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
}
free(lhost);
sControl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sControl == -1)
{
if (ftplib_debug)
perror("socket");
return 0;
}
if (setsockopt(sControl,SOL_SOCKET,SO_REUSEADDR,
SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
{
if (ftplib_debug)
perror("setsockopt");
net_close(sControl);
return 0;
}
if (connect(sControl, (struct sockaddr *)&sin, sizeof(sin)) == -1)
{
if (ftplib_debug)
perror("connect");
net_close(sControl);
return 0;
}
ctrl = calloc(1,sizeof(netbuf));
if (ctrl == NULL)
{
if (ftplib_debug)
perror("calloc");
net_close(sControl);
return 0;
}
ctrl->buf = malloc(FTPLIB_BUFSIZ);
if (ctrl->buf == NULL)
{
if (ftplib_debug)
perror("calloc");
net_close(sControl);
free(ctrl);
return 0;
}
ctrl->handle = sControl;
ctrl->dir = FTPLIB_CONTROL;
ctrl->ctrl = NULL;
ctrl->data = NULL;
ctrl->cmode = FTPLIB_DEFMODE;
ctrl->idlecb = NULL;
ctrl->idletime.tv_sec = ctrl->idletime.tv_usec = 0;
ctrl->idlearg = NULL;
ctrl->xfered = 0;
ctrl->xfered1 = 0;
ctrl->cbbytes = 0;
if (readresp('2', ctrl) == 0)
{
net_close(sControl);
free(ctrl->buf);
free(ctrl);
return 0;
}
*nControl = ctrl;
return 1;
}
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.