Socket编程实现文件的传输

客户端执行方式:
./a.out src
其中src代表要进行传输的源文件,目标文件会在服务器端自动生成一个文件,并将客户端传送过来的src文件内容全部写入到服务器所建立的文件中;可以通过md5sum +文件名 的方式来查看src文件和服务器端中生成的文件的内容是否相等;

客户端:

/*************************************************************************
	* File Name: client.c
	* Author:    The answer
    * Function:  Other        
	* Mail:      [email protected] 
	* Created Time: 2017年06月15日 星期四 18时54分22秒
 ************************************************************************/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAXSIZE 4096
#define IP "127.0.0.1"
#define SERV_PORT 8000

void sys_err(const char *ptr,int num)
{
    perror(ptr);
    exit(num);
}

int main(int argc,char **argv)
 {
    // ./a.out src
    int sockfd;
    char buf[MAXSIZE];
    struct sockaddr_in addr;

    //建立socket套接字
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0)
        sys_err("socket",-1);

    bzero(&addr,sizeof(addr));

    //初始化ip+port
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SERV_PORT);
    addr.sin_addr.s_addr = inet_addr(IP);

    //connect将sockfd套接字描述符与服务器端的ip+port联系起来
    if(connect(sockfd,(struct sockaddr *)&addr,sizeof(addr)) < 0)
        sys_err("connect",-2);

    
    //打开读的文件
    const char *src = argv[1];
    int fd = open(src,O_RDONLY);
    if(fd < 0)
        sys_err("open",-3);

    while(1)
    {
        int len = read(fd,buf,sizeof(buf));
        if(len == 0)
            break;
        
        int _tmp = 0;
        //考虑若socket缓冲区小于len的情况,见原理图1
        while(1)
        {
            int ret = write(sockfd,buf + _tmp, len - _tmp);
            if(ret > 0 )
                _tmp += ret;
            if(_tmp == ret)
                break;
            if(ret < 0)
            {
                perror("write");
                break;
            }
        }
    
    }
    
    close(sockfd);
    return 0;
 }


Socket编程实现文件的传输_第1张图片

                         图1

服务端:

/*************************************************************************
 * File Name: server.c
 * Author:    The answer
 * Function:  Other        
 * Mail:      [email protected] 
 * Created Time: 2017年06月15日 星期四 17时02分26秒
 ************************************************************************/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERV_PORT 8000

//封装出错函数
void sys_err(const char *ptr,int num)
{
    perror(ptr);
    exit(num);
}

int main(int argc,char **argv)
{
    signal(SIGPIPE,SIG_IGN);
    int sockfd,accefd;
    struct sockaddr_in seraddr,cliaddr;
    socklen_t len;

    bzero(&seraddr,sizeof(seraddr));
    bzero(&cliaddr,sizeof(cliaddr));

    //socket
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0)
    {
        sys_err("socket",-1);
    }

    //初始化ip地址+port端口号
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(SERV_PORT);
    seraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    //bind
    if(bind(sockfd,(struct sockaddr *)&seraddr,sizeof(seraddr)) < 0)
    {
        sys_err("bind",-2);
    }

    //listen
    if(listen(sockfd,128) < 0 )
    {
        sys_err("listen",-3);
    }
    //accept
    while(1)
    {
        char buf[4096];
        len = sizeof(cliaddr);
        accefd = accept(sockfd,(struct sockaddr *)&cliaddr,&len);
        if(accefd < 0)
        {
            if(errno == EINTR)  //判断阻塞等待客户端的链接;是被信号打断还是其它因素
                continue;
            else
                sys_err("accept",-4);
        }
        //开始文件的读写操作
        memset(buf,0x00,sizeof(buf));
        int filefd = open("copy.txt",O_WRONLY |O_CREAT |O_TRUNC,0777);
        while(1)
        {
            if(filefd < 0)
                sys_err("open",-5);

            int leng = read(accefd,buf,sizeof(buf));
            if(leng == 0)
            {
                printf("Opposite have close the socket.\n"); 
                break; //表示文件已经读到了结尾,也意味着客户端关闭了socket
            }
            if(leng == -1 && errno == EINTR)
                continue;
            if(leng == -1 )
                break; //表示出现了严重的错误
            write(filefd,buf,leng);

        }

        //若文件的读写已经结束,则关闭文件描述符
        close(filefd);
        close(accefd);
    }
    close(sockfd);
    return 0;
}



你可能感兴趣的:(Linux应用开发)