代理tcp伺服器如何實現ftp功能?
大家好。
我現在在做一個tcp代理伺服器,實現轉發的功能。我有3台電腦,分別作為本地客戶端,代理伺服器以及遠程客戶端,其中代理伺服器上面有2個網卡,一個
是內網的,一個是外網的。
本地客戶機的ip:192.168.0.10
代理伺服器的ip:
內網的ip:192.168.0.1
外網的ip:202.202.68.191
遠程伺服器的ip:202.202.68.201
最終就是想在本地客戶機192.168.0.10的基礎上通過cuteftp 登陸到遠程主機202.202.68.201的ftp伺服器上面,中間是
通過代理伺服器實現轉發的功能。
具體代碼如下,現在能實現識別用戶名和密碼,但是在cuteftp上一直提示「數據socket建立失敗」,請各位高人指點,這個代碼該怎麼修改和添加
才能實現ftp功能。在此先感謝了。
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <fcntl.h>
#define TCP_PROTO "tcp"
int proxy_port; /* port to listen for proxy connections on */
struct sockaddr_in hostaddr; /* remote computer's address */
extern int errno; /* defined by libc.a */
/*extern char *sys_errlist[];*/
void parse_args (int argc, char **argv);
void daemonize (int servfd);
void do_proxy (int usersockfd);
void reap_status (void);
void errorout (char *msg);
/
***************************************************************************­*
function: main
description: Main level driver. After daemonizing the process, a
socket
is opened to listen for connections on the proxy port,
connections are accepted and children are spawned to handle
each new connection.
arguments:
argc,argv you know what those are.
return value: none.
calls: parse_args, do_proxy.
globals: reads proxy_port.
***************************************************************************­*/
main (argc,argv)
int argc;
char **argv;
{
int clilen;
int childpid;
int sockfd, newsockfd;
struct sockaddr_in servaddr, cliaddr;
parse_args(argc,argv);
/* prepare an address struct to listen for connections */
bzero((char *) &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = proxy_port;
/* get a socket... */
if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
fputs("failed to create server socket",stderr);
exit(1);
}
printf("Create socket successful!\n");
/* ...and bind our address and port to it */
if (bind(sockfd,(struct sockaddr *) (&servaddr),sizeof(servaddr))
< 0) {
fputs("faild to bind server socket to specified port",stderr);
exit(1);
}
printf("Bind host succeed!\n");
/* get ready to accept with at most 5 clients waiting to connect
*/
listen(sockfd,5);
printf("listening \n");
/* turn ourselves into a daemon */
daemonize(sockfd);
/* fall into a loop to accept new connections and spawn children
*/
while (1) {
/* accept the next connection */
clilen = sizeof(struct sockaddr_in);
newsockfd = accept(sockfd, (struct sockaddr *) (&cliaddr),
&clilen);
printf("Create new connection!\n");
if (newsockfd < 0 && errno == EINTR)
continue; /* a signal might interrupt our accept() call */
else if (newsockfd < 0)
/* something quite amiss -- kill the server */
errorout("failed to accept connection");
/* fork a child to handle this connection */
if ((childpid = fork()) == 0) {
close(sockfd);
do_proxy(newsockfd);
exit(0);
}
/* if fork() failed, the connection is silently dropped --
oops! */
close(newsockfd);
}
}
/
***************************************************************************­*
function: parse_args
description: parse the command line args.
arguments:
argc,argv you know what these are.
return value: none.
calls: none.
globals: writes proxy_port, writes hostaddr.
***************************************************************************­*/
void parse_args (argc,argv)
int argc;
char **argv;
{
int i;
struct hostent *hostp;
struct servent *servp;
unsigned long inaddr;
struct {
char proxy_port ;
char isolated_host ;
char service_name ;
} pargs;
/*input is abnormal*/
if (argc < 4) {
printf("usage: %s <proxy-port> <remote host> <server-name|port-
number>\r\n",argv);
exit(1);
}
strcpy(pargs.proxy_port,argv);
strcpy(pargs.isolated_host,argv);
strcpy(pargs.service_name,argv);
for (i = 0; i < strlen(pargs.proxy_port); i++)
if (!isdigit(*(pargs.proxy_port + i))) break;
if (i == strlen(pargs.proxy_port))
proxy_port = htons(atoi(pargs.proxy_port));
else {
printf("%s: invalid proxy port",pargs.proxy_port);
exit(0);
}
bzero(&hostaddr,sizeof(hostaddr));
hostaddr.sin_family = AF_INET;
if ((inaddr = inet_addr(pargs.isolated_host)) != INADDR_NONE)
bcopy(&inaddr,&hostaddr.sin_addr,sizeof(inaddr));
else if ((hostp = gethostbyname(pargs.isolated_host)) != NULL)
bcopy(hostp->h_addr,&hostaddr.sin_addr,hostp->h_length);
else {
printf("%s: unknown host",pargs.isolated_host);
exit(1);
}
if ((servp = getservbyname(pargs.service_name,TCP_PROTO)) !=
NULL)
hostaddr.sin_port = servp->s_port;
else if (atoi(pargs.service_name) > 0)
hostaddr.sin_port = htons(atoi(pargs.service_name));
else {
printf("%s: invalid/unknown service name or port
number",pargs.service_name);
exit(1);
}
}
/
***************************************************************************­*
function: daemonize
description: detach the server process from the current context,
creating a pristine, predictable environment in which it
will execute.
arguments:
servfd file descriptor in use by server.
return value: none.
calls: none.
globals: none.
***************************************************************************­*/
void daemonize (servfd)
int servfd;
{
int childpid, fd, fdtablesize;
/* ignore terminal I/O, stop signals */
signal(SIGTTOU,SIG_IGN);
signal(SIGTTIN,SIG_IGN);
signal(SIGTSTP,SIG_IGN);
/* fork to put us in the background (whether or not the user
specified '&' on the command line */
if ((childpid = fork()) < 0) {
fputs("failed to fork first child",stderr);
exit(1);
}
else if (childpid > 0)
exit(0); /* terminate parent, continue in child */
setsid();
/* dissociate from process group */
/*
if (setpgrp(0,getpid()) < 0) {
fputs("failed to become process group leader",stderr);
exit(1);
}
*/
/* lose controlling terminal */
if ((fd = open("/dev/tty",O_RDWR)) >= 0) {
ioctl(fd,TIOCNOTTY,NULL);
close(fd);
}
/* close any open file descriptors */
for (fd = 0, fdtablesize = getdtablesize(); fd < fdtablesize; fd+
+)
if (fd != servfd) close(fd);
/* set working directory to / to allow filesystems to be
unmounted */
chdir("/");
/* clear the inherited umask */
umask(0);
/* setup zombie prevention */
/*
signal(SIGCLD,reap_status);
*/
}
/
***************************************************************************­*
function: do_proxy
description: does the actual work of virtually connecting a client to
the telnet service on the isolated host.
arguments:
usersockfd socket to which the client is connected.
return value: none.
calls: none.
globals: reads hostaddr.
***************************************************************************­*/
void do_proxy (usersockfd)
int usersockfd;
{
int isosockfd;
fd_set rdfdset;
int connstat;
int iolen;
char buf ;
/* open a socket to connect to the isolated host */
if ((isosockfd = socket(AF_INET,SOCK_STREAM,0)) < 0)
errorout("failed to create socket to host");
printf("Succeed in creating new socket!\n");
/* attempt a connection */
connstat = connect(isosockfd,(struct sockaddr *)
&hostaddr,sizeof(hostaddr));
printf("Attempt a connection.\n");
switch (connstat) {
case 0:
break;
case ETIMEDOUT:
case ECONNREFUSED:
case ENETUNREACH:
strcpy(buf,strerror(errno)); /* sys_errlist outdated, we use
use strerror function now.added by liaoy*/
strcat(buf,"\r\n");
write(usersockfd,buf,strlen(buf));
close(usersockfd);
exit(1); /* die peacefully if we can't establish a connection
*/
break;
default:
errorout("failed to connect to host");
}
/* now we're connected, serve fall into the data echo loop */
while (1) {
/* Select for readability on either of our two sockets */
FD_ZERO(&rdfdset);
FD_SET(usersockfd,&rdfdset);
FD_SET(isosockfd,&rdfdset);
if (select(FD_SETSIZE,&rdfdset,NULL,NULL,NULL) < 0)
errorout("select failed");
/* is the client sending data? */
if (FD_ISSET(usersockfd,&rdfdset)) {
if ((iolen = recv(usersockfd,buf,sizeof(buf),0)) <= 0)
break; /* zero length means the client disconnected */
send(isosockfd,buf,iolen,0);
printf("Client sends data :%s",buf);
}
/* is the host sending data? */
if (FD_ISSET(isosockfd,&rdfdset)) {
if ((iolen = recv(isosockfd,buf,sizeof(buf),0))<= 0)
break; /* zero length means the host disconnected */
send(usersockfd,buf,iolen,0);
printf("Host sends data: %s",buf);
}
}
/* we're done with the sockets */
close(isosockfd);
close(usersockfd);
}
/
***************************************************************************­*
function: errorout
description: displays an error message on the console and kills the
current process.
arguments:
msg message to be displayed.
return value: none -- does not return.
calls: none.
globals: none.
***************************************************************************­*/
void errorout (msg)
char *msg;
{
FILE *console;
console = fopen("/dev/console","a");
fprintf(console,"proxyd: %s",msg);
fclose(console);
exit(1);
}
/
***************************************************************************­*
function: reap_status
description: handle a SIGCLD signal by reaping the exit status of the
perished child, and discarding it.
arguments: none.
return value: none.
calls: none.
globals: none.
***************************************************************************­*/
void reap_status ()
{
int pid;
union wait status;
while ((pid = wait3(&status,WNOHANG,NULL)) > 0); /* loop while
there are more dead children */
《解決方案》
請高人指點,謝謝
《解決方案》
我也遇到類似的問題,客戶端連到代理提示是失敗的,但伺服器端已經收到請求了。不知你的問題解決了沒有,能否分享下。