多路复用的select的tcp server,包含了上传下载的功能

来源:互联网 发布:rsync windows 编辑:程序博客网 时间:2024/06/04 20:09
//下面是示例代码:
//代码是服务器TCP模型,采用多路复用的select函数实现了循环的监听并接受客户端的功能,其中也包含了上传下载的功能*/
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>
#include<string.h>
#include<netinet/in.h>
#include<sys/ioctl.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/types.h>
#include<dirent.h>
 
int main()
{
    struct sockaddr_in seraddr,cliaddr;
    int listenfd,connfd,fd1,fd2,n,m,l,port;
    char user[20],buf[4096];
    fd_set  readfds,tmpfds;//岗哨监控集合
    socklen_t addrlen;
    DIR *dr;
    struct dirent *file;
 
    printf("请输入需要设定的服务器名称:");
    scanf("%s",user);
     
    printf("请输入需要设定的服务器端口:");
    scanf("%d",&port);
    getchar();
 
    if((listenfd=socket(AF_INET,SOCK_STREAM,0))<0)
    {
        perror("创建失败");
       exit(-1);
    }
     
     
 
    /*开始设定服务器的参数地址类型,IP,PORT*/
    memset(&seraddr,0,sizeof(seraddr));//将服务器的初值空间清空,防止转化过程有影响
    seraddr.sin_family=AF_INET;
    seraddr.sin_port=htons(port);//将得到的本地端口转换为网络字节序
    seraddr.sin_addr.s_addr=htonl(INADDR_ANY);//将得到的ip地址字符串转换为网络字节序的ip地址数值
 
    if((bind(listenfd,(struct sockaddr*)&seraddr,sizeof(seraddr))<0))
    {
        perror("绑定失败");
       exit(-1);
    }
    printf("绑定创建\n");
    if((connfd=listen(listenfd,50))<0)
    {
        perror("监听失败");
        exit(-1);
    }
    printf("开始监听\n");
    FD_ZERO(&readfds);//初始化文件集
    FD_SET(listenfd,&readfds);//将需要监视的listenfd放入readfds集中
 
    while(1)//循环监听
    {
        int nread,n;
        tmpfds=readfds;//将监视集传递给临时的监视集中,防止后续的操作修改了监视集
        if(select(FD_SETSIZE,&tmpfds,NULL,NULL,NULL)<0)//设置监视,监视tmpfds内的子fd变化,发生变化的将会被保留在tmpfds中
          {
           perror("监视未成功");
            exit(-1);
         }
         
         for(fd1=0;fd1<FD_SETSIZE;fd1++)//循环找在最大范围内的fd1
        {
           if(FD_ISSET(fd1,&tmpfds))//查找是否fd1在tmpfds里面
            {
              if(fd1==listenfd)//判定fd1等于监听fd,即监听fd在监视过程中出现变化被发现
              {
                  addrlen=sizeof(cliaddr);
                 connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&addrlen);//开始接收客户
                 FD_SET(connfd,&readfds);//将connfd加入监视集,监视接入的变化
                 printf("接入新的连接\n");
              }
              else
                  {
                      ioctl(fd1,FIONREAD,&nread);//测试在fd中还有nread个字符需要读取
                      if(nread==0)//如果需要读取的数据为0,则关闭检测出来的fd1,并且从监视中移除
                    {
                     close(fd1);
                     FD_CLR(fd1,&readfds);
                      printf("移除\n");
                    }
                      else//如果可读数据不为0,则读出来
                    {
                        int i;
                        char *p=NULL,*q=NULL;
                      n=read(fd1,buf,nread);
                      buf[n]=0;
                      p=buf;
                       
                       
                          if((strncmp(p,"-get",4)==0))
                          {  
                             q=p+5;
                             printf("客户下载文件>%s",q);
                             if((fd2=open(q,O_RDONLY))<0)
                                 perror("打开文件错误");
                             
                             while((m=read(fd2,buf,4096))>0)
                             {
                                 write(connfd,buf,m);
                                  
                             }
                             bzero(buf,sizeof(buf));
                             close(fd1);
                             close(fd2);
                             FD_CLR(fd1,&readfds);
                           
                          }
                           
                          if((strncmp(p,"-up",3)==0))
                          {  
                             q=p+4;
                             printf("客户上传文件%s\n",buf+4);
                             if((fd2=open(q,O_CREAT | O_WRONLY | O_APPEND ,0666))<0)
                             {
                                perror("打开文件写入失败");
                                  
                             }
                              
                             while((m=read(connfd,buf,128))>0)
                             
                                 printf("%s",buf);
                                 write(fd2,buf,m);
                             }
                             bzero(buf,sizeof(buf));
                             close(fd1);
                             close(fd2);
                             FD_CLR(fd1,&readfds);
                           
                          }
                           
                          if((strncmp(p,"-ls",3)==0))
                          {  
                             q=p+4;
                             printf("客户查看文件……");
                             if((dr=opendir(q))==NULL)
                                 perror("打开目录失败");
                             while((file=readdir(dr))!=NULL)
                             {
                                   printf("%s    ",file->d_name);
                                  write(connfd,file->d_name,sizeof(file->d_name));
 
                             }
                             close(fd1);
                             close(connfd);
                             closedir(dr);
                             FD_CLR(fd1,&readfds);
                           
                          }
                       
                      printf("从客户收取的信息:%s\n",buf);
                    }
 
 
                  }
 
            }//end if 0
             
          
        }//end for 0
 
     
    }//end while0
     
    exit(0);
}//end main