//check if write data has caught read data
if (cq.fi[i].buf_sd_written == cq.fi[i].buf_sd_avail)
cq.fi[i].buf_sd_written = cq.fi[i].buf_sd_avail = 0;
if (cq.fi[i].buf_fd_written == cq.fi[i].buf_fd_avail)
cq.fi[i].buf_fd_written = cq.fi[i].buf_fd_avail = 0;
//one side has closed the connection,
//keep writing to the other side until empty
if (cq.fi[i].sd<0 && cq.fi[i].buf_sd_avail==cq.fi[i].buf_sd_written)
shut_fd(&cq,i);
if (cq.fi[i].fd<0 && cq.fi[i].buf_fd_avail==cq.fi[i].buf_fd_written)
shut_sd(&cq,i);
//resource recycling
if (shutflag == 1)
if (cq.fi[i].sd<0 && cq.fi[i].fd<0)
{
cout<<"connection["<<i<<"] recycled !"<<endl;
cq.navail ++;
}
} // end of : for (i=0;i<FWD_MAX && nsel>0;i++)
} // end of : for(;;)
return 0;
} // end of : main()
static int listen_socket(int listen_port)
{
struct sockaddr_in addr;
int s;
int yes;
if ((s=socket(AF_INET,SOCK_STREAM,0))<0)
{
cout<<"socket() for fwd_from func. error :"<<strerror(errno)<<endl;
return -1;
}
if (cfd<0)
{
cout<<"accept() func. error :"<<strerror(errno)<<endl;
close(cfd);
return;
}
//cout<<"accept() func. ok !"<<endl<<cq->navail<<endl;
if (cq->navail == 0)
{
cout<<"system has reached to the MAX connetions !"<<endl;
cout<<"to change this MAX value, please redefine FWD_MAX !"<<endl;
cout<<"request from "<<inet_ntoa(cli.sin_addr)<<" was refused !"<<endl;
close(cfd);
return;
}
cout<<"accepted fwd request from :"<<inet_ntoa(cli.sin_addr)<<endl;
///////////////
//
// tfm = TCP forwording multiplex
//
// to run : ./a.out 8086 211.148.211.38
//
// to test : telnet 127.0.0.1 8086
//
// then you will se some kind of "George Hill's FTP"
//
// Good luck !
//
///////////////
struct fwd_info
{
int sd;
int fd;
char buf_sd[BUF_SIZE];
char buf_fd[BUF_SIZE];
int buf_sd_avail,buf_sd_written;
int buf_fd_avail,buf_fd_written;
}fi[FWD_MAX];
};
for (i=0;i<FWD_MAX;i++)
{
if (cq.fi[i].sd>0)
{
if (cq.fi[i].buf_sd_avail<BUF_SIZE)
FD_SET(cq.fi[i].sd,&rds);
if (cq.fi[i].buf_fd_avail>cq.fi[i].buf_fd_written)
FD_SET(cq.fi[i].sd,&wds);
FD_SET(cq.fi[i].sd,&eds);
maxfd = max(maxfd,cq.fi[i].sd);
}
if (cq.fi[i].fd>0)
{
if (cq.fi[i].buf_fd_avail<BUF_SIZE)
FD_SET(cq.fi[i].fd,&rds);
if (cq.fi[i].buf_sd_avail>cq.fi[i].buf_sd_written)
FD_SET(cq.fi[i].fd,&wds);
FD_SET(cq.fi[i].fd,&eds);
maxfd = max(maxfd,cq.fi[i].fd);
}
}// end of : for (i=0;i<FWD_MAX;i++)
nsel = select(maxfd+1,&rds,&wds,&eds,NULL);
if (r==-1 && errno == EINTR)
continue;
if (r<-1)
{
cout<<"select() func. error !"<<errno<<strerror(errno)<<endl;
return (-1);
}
if (FD_ISSET(cq.lfd,&rds))
{
accept_conn(&cq);
nsel--;
}
// NB: read oob data before normal reads
for (i=0;i<FWD_MAX && nsel>0;i++)
{
//假如编程开始就使用以下类似语句,书写效率会高不少;
//也不容易出错;
const int sd = cq.fi[i].sd,fd = cq.fi[i].fd;
int shutflag = 0;
//把man例子顺序稍微调整了一下。
if (sd>0)
{
if (FD_ISSET(sd,&eds))
{
char c;
errno = 0;
r = recv(sd,&c,1,MSG_OOB);
if (r<1)
{
if (r == 0)
cout<<"some error on fwd_from["<<i<<"] !"<<endl;
shut_sd(&cq,i);
}
else
send(fd,&c,1,MSG_OOB);
nsel --;
}
if (FD_ISSET(sd,&rds))
{
r= read(sd,cq.fi[i].buf_sd+cq.fi[i].buf_sd_avail,BUF_SIZE-cq.fi[i].buf_sd_avail);
if (r<1)
{
if (r == 0)
cout<<"fwd_from["<<i<<"] has closed the connection ! and read action returns !"<<endl;
if (FD_ISSET(sd,&wds))
{
r= write(sd,cq.fi[i].buf_fd+cq.fi[i].buf_fd_written,cq.fi[i].buf_fd_avail-cq.fi[i].buf_fd_written);
if (r<1)
{
if (r == 0)
cout<<"fwd_from["<<i<<"] has closed the connection ! and write action returns zero !"<<endl;