当前位置: 首页 >> 网络协议与安全 >> TCP实现文件传输的代码实现与启发
 

TCP实现文件传输的代码实现与启发

作者:      来源:zz     发表时间:2006-07-14     浏览次数:      字号:    

原文是在
http://bbs.chinaunix.net/viewthread.php?tid=57032
上发布的(好像这个地址的也是转载^_^)
不过文章中提供的源代码问题确实太多了,昨天一位网友求助让我帮其调试程序,一看,想不到竟是这片文章提供的代码,而且自己还回过贴,呵呵,真是有缘,晚上便将代码调试了一下,顺便做了些格式上的修改,相信大概的思想大家都已经明白了,今天早上调通了试了试还不错,传了个图片和应用程序,蛮快的,贴出来与大家分享一下:

(1):首先在/etc/host中添加Server地址,我的机上是这样

[root@localhost root]# cat /etc/hosts
# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1               localhost.localdomain localhost
只需要在下面的一行添加上

192.168.1.21    localhost.localdomain Server
就可以了,当然,这里的192.168.1.21要改成你的server端程序所在的机子的IP地址,其次,Server
可以随便改成你喜欢的名字,阿毛阿狗都可以,只要跟后面程序中的host_name中一致就行了
下面贴出代码
服务器端,也就是文件存放端的程序

/**********************FileServer.c******************************/
//Author: May be duanjigang, ^_^
#include<stdio.h>
#include<sys/types.h>
#include<sys/fcntl.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#define command "clear"
//这里其实应改写成ifdef _WIN32 define command "cls" else define "clear",更合理些
#include<errno.h>
#define  big_size  2048
#define small_size  50
int main(void)
{
        char c= 0,
        buf[big_size],//读文件的缓冲
        file[small_size],//文件名
  host_name[small_size];//主机名
        int fromlen = 0,source = 0;
        register int k,s,ns;
        struct sockaddr_in sin;
        struct hostent * hp;
        system(command);//清屏
        printf("输入要传输的文件名:");
        memset(file, 0, small_size);
        scanf("%s",file);
        if ((source = open(file, O_RDONLY) ) < 0)
        {
                perror("源文件打开出错");
                exit(1);
        }
        memset(host_name, 0, small_size);
  //写入server的名子,然后gethostbyname将会根据这个名子去找主机的信息
  sprintf(host_name, "%s", "Server");
        if((hp = gethostbyname(host_name)) == NULL)
        {
                   perror("返回主机地址信息错!!!");
                   exit(2);
        }
        if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
                   printf("获取SOCKET号失败!!!");
                   exit(3);
        }
        sin.sin_family=AF_INET;
        sin.sin_port=htons(1500);
        memcpy(&sin.sin_addr, hp->h_addr, hp->h_length);
        if(bind(s, (struct sockaddr*)&sin, sizeof(sin)) < 0 )
        {
                   printf("不能将服务器地址捆绑到SOCKET号上!!!\n");
                   close(s);
                   exit(4);
        }
         if(listen(s,5) < 0)
         {
                   fprintf(stderr, "sever:listen\n");
                   exit(5);
         }
          while(1)
          {
                   printf("等待传送文件中.......\n");
                   if((ns = accept(s, NULL, NULL)) < 0 )
                   {
                           fprintf(stderr, "sever:accept\n");
                           exit(6);
                   }
                   lseek(source,0L,0);
                   printf("开始传送文件.....\n");
        //先把文件名发过求
                   write(ns,file,sizeof(file));
                   printf("%s\n", file);
                   //发送文件名
                   memset(buf, 0, big_size);
                   while( (k = read(source, buf, sizeof(buf))) > 0)
                   {
                             //循环发送直到,文件结束
                             write(ns,buf,k);
                       memset(buf, 0, big_size);
                   }
                   printf("\n传输完毕\n");
                   close(ns);
           }
           close(source);
           exit(0);
}  
[code]
客户端,即要下载文件的机子端程序
[code]
/*****************************FileClient.c********************************/
#include<stdio.h>
#include<sys/types.h>

#include<sys/fcntl.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#define command "clear"

#include<errno.h>
#include <string.h>

#define big_size 1024
#define small_size 50

int main(void)
{
        char buf[big_size] ={0},file[small_size]={0},
         host_name[small_size]={0};
        int target,ret;
        register int bytes,sockfd;
        struct sockaddr_in sin ;
        struct hostent *hp;
        system(command);
               sprintf(host_name, "%s", "Server");
        if((hp = gethostbyname(host_name)) == NULL)
        {
                fprintf(stderr, "返回服务器地址信息错!!!\n");
                exit(1);
        }
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0 )) < 0)
        {
                fprintf(stderr, "获取SOCKET号失败!!!\n");
                exit(2);
        }
       
        memset((char*)&sin, '\0', sizeof(sin));
       
        sin.sin_family = AF_INET;
        sin.sin_port = htons(1500);
  
        sin.sin_addr = *(struct in_addr*)hp->h_addr;
        if((ret = connect(sockfd, (struct sockaddr*)&sin, sizeof(sin))) == -1)
        {
                fprintf(stderr, "不能与服务器连接!!!\n");
                exit(3);
        }
        memset(buf, 0, big_size);
        while(read(sockfd, file, sizeof(file)) < 0);       
        sprintf(buf, "%s_%s", "receive", file);

        if((target=open(buf, O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0)
        {
                perror("不能打开目标文件!!");
                exit(4);
        }
       
        memset(buf, 0, big_size);
        while((bytes = read(sockfd, buf, sizeof(buf))) > 0)
        {
                write(target,buf,bytes);
                memset(buf, 0, big_size);       
        }
        printf("接收文件成功!!!\n");
        close(sockfd);
        close(target);
}
后话
(1):实现windows和Linux的多平台程序,昨天在windows下调通了,可是客户端老是出错,就没做太多研究,有兴趣的朋友可以尝试一下。
(2):今天忽然想到,既然都做到这个地步了,我们为何不把它作成一个FTP程序,而且,考虑到多客户串行端传输比较费时,所以最好在accept到一个客户端的时候就生成一个线程,实现并行下载,对于FTP我也不是很懂,不过觉的这样应改可以实现吧,后面有空了一定要尝试的,在此先提一下自己的想法,有兴趣的朋友可以自己实现一下,呵呵,最近太忙了,都没时间光顾CU了,学习,学习。。。。。。。。

责任编辑 webmaster

 
 
 
 
 
评论更多>>
 
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •