基于linux的文件传输器实现详解----客户端实现详解

        我们天天用QQ传送文件,也习惯了用飞鸽传送文件。但里边的具体实现是怎么样的呢?其实,过程很多简单,相信大家都知道,我这里呢,就多此一举给大家详细分析分析,做个总结,也为网络程序的编写搭一个整体的框架。好了,现在开始,我会分为两个端来说明:客户端和服务器端。今天先说客户端,下次再说服务器端。
        直接上源码,来的简单实用且讲解不费劲,文中的代码是完整的代码,行文中蓝色部分是说明部分,使用时去掉及可以了,现在开始:

        作为C语言,当然是先来个main()了:

int main(int argc,char**argv)
{
    if(argc !=2) //输入命令提示信息
    {
        printf("Please enter command like this: %s ServerIPAddress\n",argv[0]);
        exit(1);
    }
    int i=0;
    for(i;i<1000;i++)    //做循环是为了不想结束程序,想多次传输
        SendRequest(argv);     //传输的核心当然是从这里开始了
    return 0;
}
        通过上面我们知道了问题的核心就集中在SendRequest(argv)上,我们继续往下走:

void SendRequest(char**argv)
{   
    int client_socket = socket(AF_INET,SOCK_STREAM,0);   //创建客户端连接套接字
    int ret;  //建立连接的返回值
    if(client_socket<0)
    {
        printf("Create socket failed!\n");
        exit(1);
    }   
    struct sockaddr_in server_addr;  //设置一个socket地址结构server_addr,代表服务器的internet地址, 端口
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;   
    if(inet_aton(argv[1],&server_addr.sin_addr)==0) //服务器的IP地址来自程序的参数 
    {//inet_aton将一个参数的点分十进制IP地址转换为32位网络字节序二进制IP地址
        printf("Server IP address error!\n");
        exit(1);
    }
    server_addr.sin_port = htons(SERVER_PORT);
    socklen_t server_addr_length = sizeof(server_addr); 
    //向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接
    if((ret=connect(client_socket,(struct sockaddr*)&server_addr,server_addr_length))<0)
    {
            printf("Connect %s failed!\n",argv[1]);
        exit(1);
    }

        上边这段应该还行吧,先创建一个客户端套接口,这个很重要,后面的和服务器连接,接收服务器信息都用这个套接口。然后就是定义服务器端套接口(server_addr),里边包含了IP地址啦,端口信息啦,反正靠这个就能找到远端服务器,接下来,就是将我们刚创建的本地套接口client_socket和服务器套接口建立一个通信管道(连接),这里很明显就是connect,是不。继续:

char file_name[FILE_NAME_MAX_SIZE+1];  //存储文件名的缓冲区
bzero(file_name,FILE_NAME_MAX_SIZE+1);
printf("Please enter the file name you want to open:\t");
scanf("%s",file_name);     //输入要获得的文件的名(对应服务器端的完整路径)
char buffer[BUFFER_SIZE];
bzero(buffer,BUFFER_SIZE);
strncpy(buffer,file_name,strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name));
send(client_socket,buffer,BUFFER_SIZE,0);   //向服务器发送buffer中的数据,就是告诉服务器我要buffer里对应的文件
FILE * fp = fopen(file_name,"w");           //同时在本地建立一个这样的文件,以便后面服务器传来的文件内容放进去

        这一段也应该没有问题,注释中已经说的很明白了。一旦在上面建立了连接,这时就要告诉服务器我要接受你的啥文件(file_name),然后本地创建一个文件以便准备接收服务器传过来的东西。

bzero(buffer,BUFFER_SIZE);   //刚buffer里存的是客户端想要的文件名,现在我们里边打算放服务器传过来的文件内容
int length = 0;
int write_length=0;      //每次从服务器端接收文件内容的大小
while(length=recv(client_socket,buffer,BUFFER_SIZE,0))    //文件可能很大,一次只能接收一点,所以当然要用循环接收完
{//client_socket派上用场了,我前边说过,它和服务器的套接口地址信息建立了一个管道,那么服务器来的信息当然就存在它里边了,我们只要拷贝到buffer就好了
    if(length<0)    //奇怪,我居然没从里边接收到内容即内容长度为空
    {
        printf("Receive data from %s failed!\n",argv[1]);
        break;
    }
    write_length = fwrite(buffer,sizeof(char),length,fp);  //成功的服务器写入客户端套接字的client_socket中读到了数据,那就写到fp中吧
    if(write_length<length)   //写入的怎么会小于接收到的呢, 肯定出错了
    {
        printf("File %s write failed!\n",file_name);
        break;
    }
    bzero(buffer,BUFFER_SIZE);    //为了避免混淆,还是清空接收的缓冲区吧
}
 
if(write_length<=0)    //这明显是出错了啊
{
    printf("File %s dosen't exist!\n",file_name);
    exit(1);
}

        这一段是关键,我刚才说了,既然在本地套接口client_socket和服务器信息套接口地址上建立了连接,那么和服务器的所有通信就丢给了client_socket.一旦服务器有信息要写回给客户端,客户端的接口就是client_socket,r,然后我们只要把这里边的信息写入buffer,然后把buffer里的信息写入本地文件的文件描述符就好了(fd).最后说明的是我们用了循环,是因为谁也不能拍着胸脯说,能一下子接收完,网络的能力还是有限的,那就循环判断当服务器发过来的信息长度为0时,我就认为是传输结束了。当所有的一切都结束了,好那就关闭以前建立的连接啦,文件描述符啦,套接口啦:

    close(fp);
    close(client_socket);
}

        代码讲完了,其实相当简单,刚都说了,我是多此一举来总结下大家都知道,最后给你一个流程图:


        有了上面的流程图,现在清晰多了,服务器端的部分,我下次再讲。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值