您的位置:首页 > 理论基础 > 计算机网络

网络间通信socket传输任意格式任意大小的文件

2012-07-05 09:03 453 查看
http://blog.csdn.net/hdw10/article/details/7497760

      最近看到很多网友写的socket程序,试验了几个,发送"Hello,world"时都没有问题,但在传输较大文件,比如一个200M的文件时,都不能成功,即使成功了,server端也存在保存的问题, 有的是乱码,也有文件大小不对的情况,这两天工作不忙,我也草草写了一些代码,实现了可以传输任意格式任意大小的文件,几位同事帮我一起做了测试,传送几百M的文件速度还是很快的,而且也没有丢数据的问题。 
代码原理很简单,所以也没有做注释,大家可以把代码copy下来,自己把玩一下。现在我跟同事之间传送datasheet,都在使用我的程序, 其实我也是个入行不深的人,代码并没有经过优化,很多printf() 是多余的,也有的地方写的很麻烦。希望大家给以批评,给以帮助。

              由于 网络接口MTU的限制(一般mtu为1500),大些的文件只能分多次发送,这样就有几个问题:分几次发送?一次发送多大? 保存端的怎么保存?

我的办法是:通过定义一个shouldoplen,来说明一次操作需要操作的长度,如果要发送的文件较小(跟buf相比),shouldoplen 就是读取的文件大小,如果文件较大,需要多次发送,那么shouldoplen 就是buf  的长度,通过多次读取,发送, 直到发送出去的总长度oplencount  等于文件的大小,这时一个文件就算完整发送成功了。

编译时:  

    gcc  socket_server.c -lpthread  -o server

    gcc  socket_client.c -o client

使用时:

在一端打开server

       #./server

令一端使用client   

     #./client ./han/docunt/Linux_dd.pdf  Linux_dd.pdf

这样就把./han/docunt/Linux_dd.pdf 这就文件  发送server端,保存名为Linux_dd.pdf        

当然,前提是在sock_client.c  中的把目的IP改为你要连接的目的IP。

***********************这是data.h****************

#ifndef DATA_H

#define DATA_H

#include<stdio.h>

#include<stdlib.h>

#include<unistd.h>

#include<string.h>

#include<fcntl.h>

#include<signal.h>

#include<pthread.h>

#include<sys/socket.h>

#include<errno.h>

#include<arpa/inet.h>

#include<netinet/in.h>

#include "data.h"

typedef  unsigned int uint;

struct data{

    char filename[30];              //要发送的文件名(可含路径)

    char filesavename[30];    //要保存的文件名(可含路径)

    

    uint filelen;                        //文件从字节数

    uint shouldoplen;             //一次要操作的字节数

    

    uint oplencount;                // 操作的字节总数

    char filebuf[1300];                //由于mtu为1500,在不改动mtu的情况下,1300没有问题。

    

};

struct data_return {

        

    int writelen;                           //server端保存文件时,一次写的长度

    

    int writelencount;                //写的总数

    

    int recvlen;                             //一次接受到的长度

};

#endif

***********************这是sock_sever 端********************************

#include "data.h"

int sockid;

pthread_t tid;

int fileopen;

__sighandler_t f_quit(void)

{

    printf("\nserver closed right now!!\n");

    close(sockid);

    close(fileopen);

    exit(0);

}

struct thread_para{

    int sockid;

    

    struct sockaddr_in addr;

    struct sockaddr_in fromaddr;

    struct data datarecv;

};

int main(int argc,char* argv[])

{

    

    signal(SIGINT,(__sighandler_t)f_quit);

    struct thread_para thread_do;

    memset(&thread_do,0,sizeof(thread_do));

    

    sockid = socket(AF_INET,SOCK_STREAM,0);

    

    if(sockid == -1)

        printf("socker create error!"),exit(-1);

    printf("sockid = %d\n",sockid);

    struct sockaddr_in addr;    

    

    addr.sin_family = AF_INET;

    addr.sin_port = htons(8888);

    addr.sin_addr.s_addr = INADDR_ANY;

    int r = bind(sockid,(struct sockaddr*)&addr,sizeof(addr));

    if(r<0) 

        printf("bind error!,r=%s\n",strerror(errno)),exit(-1);

    

    printf("bind success!\n");

    if((r = listen(sockid,10))<0)

        printf("listen error!,r=%s\n",strerror(errno)),exit(-1);

    

    printf("listen successfully!\n");

    int fd,writelen,writelencount,recvlen,opnumber;

    

    struct sockaddr_in fromaddr;

    socklen_t len = sizeof(fromaddr);

    void* handler(void*);

    while(1){

        

        

        if( (fd = accept(sockid,(struct sockaddr*)&fromaddr,&len)) < 0 ){

            printf("accept error,errno = %s\n",strerror(errno)),exit(-1);

        } 

    

        printf("accept successfuluy!,new sockid=%d\n",fd);

    

        memset(&thread_do,0,sizeof(thread_do));

    

        thread_do.sockid = fd;

        thread_do.fromaddr = fromaddr;

    

        pthread_create(&tid,NULL,handler,&thread_do);

    }

}

void* handler(void* p)

{

    struct thread_para * thread_do = p;

    int writelen,writelencount,recvlen,opnumber;

    writelen = 0;

    writelencount = 0;    

    

    recvlen = 0;

    opnumber = 1;

    printf(" there are the data from %s :\n",inet_ntoa(thread_do->fromaddr.sin_addr) );

    

    do{

        memset(&thread_do->datarecv,0,sizeof(thread_do->datarecv));

    

        recvlen = recv( thread_do->sockid,&thread_do->datarecv,sizeof(thread_do->datarecv)-1,0);        

    

        if(recvlen<0) 

            

            printf("recv error!,errro=%s\n",strerror(errno)),exit(-1);

        else if(recvlen == 0 ) 

        

            printf(" client has closed!\n");

        

        else

    

            printf("the filename from client:\n\t%s\n",thread_do->datarecv.filename);

        

            printf("the file save name:\n\t%s\n",thread_do->datarecv.filesavename);

    

            printf("the filelen =%d,the recvlen=%d,the filebuf = %d\n",thread_do->datarecv.filelen,recvlen,sizeof(thread_do->datarecv.filebuf)-1 );

            printf("the shouldoplen = %d\n",thread_do->datarecv.shouldoplen);

            printf("the oplencount = %d\n",thread_do->datarecv.oplencount);

    

            umask(0);

            int fileopen = open((const char*)thread_do->datarecv.filesavename,O_RDWR | O_CREAT | O_APPEND, S_IRWXU | S_IRWXG | S_IROTH );    

    

            if(fileopen<0){

                printf("fileopen error!,%s\n",strerror(errno)),exit(-1);

        

            }

            printf("file %s create and open successfully!\n",thread_do->datarecv.filesavename);

            if( (  writelen =  write(fileopen,thread_do->datarecv.filebuf,thread_do->datarecv.shouldoplen)  ) <0 ){

                printf("write error!\n"),exit(-1);

            }

             

            writelencount  += writelen;

            printf(" opnumber = %d,writelen=%d,writelencount=%d\n \n",opnumber++,writelen,writelencount);

            struct data_return data_r;

    

            data_r.writelen = writelen;

    

            data_r.writelencount = writelencount;    

        

            data_r.recvlen = recvlen;

            write(thread_do->sockid, &data_r ,sizeof(data_r));

        

            close(fileopen);

    

            }while( writelencount != thread_do->datarecv.filelen );

        

}    

***********************************这是sock_client 端*******************************

#include "data.h"

int sockid;

__sighandler_t f_quit(void)

{

        printf("\n client closed right now!!\n");

        close(sockid);

 

        exit(0);

  

}

int main(int argc,char* argv[])

{

    signal(SIGINT,(__sighandler_t)f_quit);

    sockid = socket(AF_INET,SOCK_STREAM,0);

    

    if(sockid==-1){

    

        printf("socket create error!"),exit(-1);

    

    }

    

    struct sockaddr_in addr;

    memset(&addr,0,sizeof(addr));

    addr.sin_family = AF_INET;

    addr.sin_port = htons(8888);

    inet_aton("192.168.10.52",&addr.sin_addr);

    

    int r = connect(sockid,(struct sockaddr*)&addr,sizeof(addr));

    if(r<0)printf("connect error!\n"),exit(-1);

    printf("connect success!  \n");

    struct data datasent;

    

    memset(&datasent,0,sizeof(datasent));

    

    struct  data_return data_r;

    memset(&data_r,0,sizeof(data_r));

    strcpy(datasent.filename, argv[1]);

    

    strcpy(datasent.filesavename,argv[2]);

    int fd  = open(datasent.filename,O_RDWR);    

    if(fd<0){

    

        printf("open %s failed!\n",datasent.filename),exit(-1);

    }

    

    datasent.filelen = lseek(fd,0,SEEK_END);

    

    lseek(fd,0,SEEK_SET);

    printf("open file %s success!,the fd = %d,file length  = %d\n",datasent.filename,fd,datasent.filelen);

    datasent.oplencount = 0;

    int opnumber = 1;

    do{

    

        lseek(fd,datasent.oplencount,SEEK_SET);

        if( (datasent.filelen - datasent.oplencount ) >= ( sizeof(datasent.filebuf) - 1 ) ){                    //  比较: ( filelen - oplencount   ) 与  filebuf 的大小        

    

            datasent.shouldoplen = sizeof(datasent.filebuf) - 1 ;                                                             //通过比较,确定出shouoplen的值

        }

        else{

            datasent.shouldoplen = datasent.filelen -datasent.oplencount;    

        }

        memset(&datasent.filebuf,0,sizeof(datasent.filebuf));

        readdata(fd,&datasent,datasent.shouldoplen);

        datasent.oplencount += datasent.shouldoplen;

        sentdata(datasent);

        printf(" opnumber = %d,shouldoplen = %d ,datasent.oplencount = %d \n",opnumber++,datasent.shouldoplen,datasent.oplencount);

        read(sockid,&data_r,sizeof(data_r));

    

        printf("server info:recvlen = %d, writelen = %d, writelencount = %d \n\n",data_r.recvlen,data_r.writelen,data_r.writelencount);

        } while( datasent.filelen > datasent.oplencount );

        close(sockid);

        close(fd);                

                                

}

int readdata(int fd,struct data* datasent,int len)

{

    int readlen;

    if((readlen = read( fd,datasent->filebuf,len ) )<0){                                                            //通过len来确定一次要读多少

        

        printf("%m\n"),exit(-1);

    }

    printf("read %s successfully ! readlen=%d\n",datasent->filename,readlen);

}

int sentdata(struct data datasent)

{

    int sendlen;    

    if((sendlen = send( sockid,&datasent,sizeof(datasent)-1,0 ))<0){

    

        printf("write error ,writelen=%d, sizeof(datasent): %d, error: %s\n",sendlen, sizeof(datasent), strerror(errno));

    

        exit(-1);

    }

    printf("file %s send successfully!,sendlen=%d\n",datasent.filename,sendlen); 

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐