在写一个FTP程序,用select实现多路复用,希望能得到点启示

软件和网站开发以及相关技术探讨
回复
头像
commando
帖子: 150
注册时间: 2005-09-21 0:27
联系:

在写一个FTP程序,用select实现多路复用,希望能得到点启示

#1

帖子 commando » 2008-12-11 22:23

好吧我直说吧,程序是老婆的project,我以前在win下学过C的一点皮毛,赶鸭子上架,只能硬着头皮写,我已经完成了链接和读入服务器传回的数据,也就是能读出服务器传回的220 .....但是之前没有接触过socket,而且对FTP协议的理解也不是很深(都是这两天临时学的),对于处理用户名,密码,和命令没怎么搞明白,希望各位能给我一点指导,谢谢了

代码: 全选

/* header files */
#include	<stdio.h>
#include	<stdlib.h>
#include	<netdb.h>
#include	<sys/socket.h>
#include	<sys/types.h>
#include	<sys/stat.h>
//#include	<netinet.h>
#include	<unistd.h>
#include	<arpa/inet.h>
#include	<fcntl.h>

#include<string.h>

#include	<netdb.h>	/* getservbyname(), gethostbyname() */
#include	<errno.h>	/* for definition of errno */


/* define macros*/
#define MAXBUF	1024
#define STDIN_FILENO	0
#define STDOUT_FILENO	1

/* define FTP reply code */
#define USERNAME	220
#define PASSWORD	331
#define LOGIN		230
#define PATHNAME	257
#define CLOSEDATA	226
#define ACTIONOK	250

/* DefinE global variables */
char	*host;		/* hostname or dotted-decimal string */
char	*port;
char	*rbuf, *rbuf1;		/* pointer that is malloc'ed */
char	*wbuf, *wbuf1;		/* pointer that is malloc'ed */
struct sockaddr_in	servaddr;


//int	cliopen(char *host, char *port);
//void	strtosrv(char *str, char *host, char *port);
void	cmd_tcp(int sockfd);
//void	ftp_list(int sockfd);
//int	ftp_get(int sck, char *pDownloadFileName_s);
//int	ftp_put (int sck, char *pUploadFileName_s);


int main(int argc, char *argv[])
{
	struct hostent *hptr;
	int	fd;

	if (0 != argc-2)
	{
		printf("%s\n","missing <hostname>");
		exit(0);
	}

	port = 21;
	if (argc!=2) return 1;
	if ((hptr=gethostbyname(argv[1]))==NULL)
	{
		printf("gethostbyname error");
		return 2;
	}
	host = inet_ntoa(*((struct in_addr *)hptr->h_addr));
	printf("Host ip: %s\n",inet_ntoa(*((struct in_addr *)hptr->h_addr)));
	//host = argv[1];
	struct sockaddr_in servaddr;
	char mybuffer[256];
	if((fd=socket(AF_INET,SOCK_STREAM,0))<0)
	{
	   printf("error in socket\n");
	   exit(1);
	}	
	else
	{
	   printf("socket created .\n");
	   printf("socked id: %d \n",fd);
	}
	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family=AF_INET;
	servaddr.sin_port=htons(port);
	servaddr.sin_addr.s_addr=inet_addr(host);

	printf("connecting to %s ...",host);
	
	//printf("%s \n",htons(port));

	if(connect(fd,&servaddr,sizeof(servaddr))<0)
	{
	   printf("connect fail\n");
	   exit(1);
	}
	else
	{   
	   printf("connect ok!\n");
	}

        cmd_tcp(fd);
	if (close(fd) < 0)
		printf("close error\n");

	//exit(0);
}

void cmd_tcp(int sockfd)
{
	int		maxfdp1, nread, nwrite, fd, replycode;
	char		host[16];
	char		port[6];
	fd_set		rset;
	char 		mybuffer[1024];

	FD_ZERO(&rset);
	maxfdp1 = sockfd + 1;	/* check descriptors [0..sockfd] */
	for (;;)
	{
		
		FD_SET(STDIN_FILENO, &rset);
		FD_SET(sockfd, &rset);

		if (select(maxfdp1, &rset, NULL, NULL, NULL) < 0)
			printf("select error\n");

		if (FD_ISSET(STDIN_FILENO, &rset)) 
		{
			if ( (nread = read(STDIN_FILENO, rbuf, MAXBUF)) < 0)
				printf("read error from stdin\n");
			nwrite = nread+5;

			/* send username */
			if (replycode == USERNAME) 
			{
				sprintf(wbuf, "USER %s", rbuf);
				if (write(sockfd, wbuf, nwrite) != nwrite)
					printf("write error\n");
			}
		
		
		}

		if (FD_ISSET(sockfd, &rset)) 
		{

			if ( (nread = recv(sockfd,mybuffer, sizeof(mybuffer), 0)) < 0)
				printf("recv error\n");
			else 
			{
				printf("%s",mybuffer);
				if (nread == 0)
				break;
			}

			/* set replycode and wait for user's input */
			if (strncmp(rbuf, "220", 3)==0 || strncmp(rbuf, "530", 3)==0){
				strcat(rbuf,  "your name: ");
				nread += 12;
				replycode = USERNAME;
			}

			/*************************************************************
			// 9. code here: handle other response coming from server
			*************************************************************/

			/* open data connection
			if (strncmp(rbuf, "227", 3) == 0) 
			{
				strtosrv(rbuf, host, port);
				fd = cliopen(host, port);
				write(sockfd, wbuf1, nwrite);
				nwrite = 0;
			}
			*/
			/* start data transfer */
			//if (write(STDOUT_FILENO, rbuf, nread) != nread)
			//	printf("write error to stdout\n");
		}
	if (close(sockfd) < 0)
		printf("close error\n");
	}	



}
这段ftp_cmd函数的代码不太明白,这是从框架里抄的,但是似乎没有实现用户名的输入,我如何才能比较有效的输入用户名,密码,命令呢。

代码: 全选

		if (FD_ISSET(STDIN_FILENO, &rset)) 
		{
			if ( (nread = read(STDIN_FILENO, rbuf, MAXBUF)) < 0)
				printf("read error from stdin\n");
			nwrite = nread+5;

			/* send username */
			if (replycode == USERNAME) 
			{
				sprintf(wbuf, "USER %s", rbuf);
				if (write(sockfd, wbuf, nwrite) != nwrite)
					printf("write error\n");
			}
		
		
		}
朱弦一抚余音在,却是当时寂寞心
头像
commando
帖子: 150
注册时间: 2005-09-21 0:27
联系:

Re: 在写一个FTP程序,用select实现多路复用,希望能得到点启示

#2

帖子 commando » 2008-12-11 22:28

是否if (FD_ISSET(STDIN_FILENO, &rset)) 就是检测FTP服务器是否有命令输入呢
朱弦一抚余音在,却是当时寂寞心
头像
percy
帖子: 508
注册时间: 2006-09-10 8:19
系统: Gentoo/Mac OS X
来自: Shanghai,China
联系:

Re: 在写一个FTP程序,用select实现多路复用,希望能得到点启示

#3

帖子 percy » 2009-01-01 0:48

可以去参考下axel的源码。
xyywll
帖子: 338
注册时间: 2008-05-24 1:24

Re: 在写一个FTP程序,用select实现多路复用,希望能得到点启示

#4

帖子 xyywll » 2009-01-01 11:01

相当练手阿~ 支持 lz~
如果努力的目的是为了超越他人,那么我们永远成功不了
大道是平的,我们该做的是让自己快乐,同时带给他人快乐
好好涵养自己的性格
才华是刀刃,辛苦是磨刀石
多食果蔬,健康长寿;少吃不吃鱼肉,珍爱它类生命,远离自身疾病
头像
qqttdh
帖子: 896
注册时间: 2007-07-20 22:15

Re: 在写一个FTP程序,用select实现多路复用,希望能得到点启示

#5

帖子 qqttdh » 2009-01-01 12:07

filezilla的实现方案应该符合您的需求
发言并不是一种义务,最喜欢的回答是不知道
两个手指点击,居然默认就是鼠标中键功能
右上角是中键,右下角是左键
Grub真小,才512B
零度电子书(Unix&Linux)
http://books.05sun.com/downlist/s_62_3.html
win7恢复能力不如xp,ubuntu相对较稳定。。。待机恢复起来似乎。。。
flyinflash
帖子: 2376
注册时间: 2006-09-21 14:28

Re: 在写一个FTP程序,用select实现多路复用,希望能得到点启示

#6

帖子 flyinflash » 2009-01-12 13:13

代码: 全选

apt-get source axel
read fucking source
回复