• linux socket c/s上传文件


    这是上传文件的一个示例,可以参照自行修改成下载或者其它功能。

    在上传时,需要先将文件名传到服务器端,这是采用一个结构体,包含文件名及文件名长度(可以用于校验),防止文件名乱码。

    client

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include "wrap.h"
    #define MAXLINE 1492
    #define SERV_PORT 5555 
    #define FILE_NAME_LEN 64
    
    struct fileInfo{
        char fileName[FILE_NAME_LEN];
        int len;
    };
    
    int main(int argc, char *argv[])
    {
        if(argc<3){
            perror("Usage:./a.out ip filename");
            exit(-1);
        }
        struct sockaddr_in servaddr;
        char buf[MAXLINE];
        int sockfd;
        //char servip[]="123.206.59.137";
        sockfd = Socket(AF_INET, SOCK_STREAM, 0);
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        inet_pton(AF_INET, argv[1], &servaddr.sin_addr);
        servaddr.sin_port = htons(SERV_PORT);
        Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
        
        struct fileInfo file_name;
        memset(&file_name,0,sizeof(file_name));
        strncpy(file_name.fileName,argv[2],strlen(argv[2]));
        file_name.len=strlen(argv[2]);
        Write(sockfd,&file_name,sizeof(file_name));
        FILE *fp=fopen(argv[2],"r");
        if(fp==NULL){
            perror("open file failed");
            Close(sockfd);
            exit(-1);
        }
        printf("open file %s successed
    ",argv[2]);
        int len=0;
        while ((len=fread(buf,sizeof(char),MAXLINE,fp))>0) {
            Write(sockfd, buf, len);
        }
        fclose(fp);
        Close(sockfd);
        return 0;
    }

    server

    #include <stdio.h>
    #include <string.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <pthread.h>
    #include "wrap.h"
    #define MAXLINE 1492
    #define SERV_PORT 5555 
    #define FILE_NAME_LEN 64
    struct fileInfo{
        char fileName[FILE_NAME_LEN];
        int len;
    };
    
    int main(int argc, char *argv[]){
        struct sockaddr_in serveraddr;
        int listenfd;
        char str[INET_ADDRSTRLEN];
        
        listenfd=Socket(AF_INET,SOCK_STREAM,0);
        bzero(&serveraddr,sizeof(serveraddr));
        serveraddr.sin_family=AF_INET;
        serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
        serveraddr.sin_port=htons(SERV_PORT);
    
        Bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
        Listen(listenfd,20);
        
        while(1){
            struct sockaddr_in clientaddr;
            socklen_t addrLen=sizeof(clientaddr);
            int confd=Accept(listenfd,(struct sockaddr *)&clientaddr,&addrLen);
            printf("receive file from %s at port %d
    ",
                inet_ntop(AF_INET,&clientaddr.sin_addr,str,sizeof(str)),
                ntohs(clientaddr.sin_port)
            );
            int len=0;
            struct fileInfo file_name;
            len=Read(confd,&file_name,sizeof(file_name));
            if(len==0){
                Close(confd);
            }else {
                printf("file name len=%d
    ",file_name.len);
                printf("file name is %s
    ",file_name.fileName);
            }
            char buf[MAXLINE];
            FILE *fp=fopen(file_name.fileName,"w");
            if(!fp){
                perror("open file failed");
                Close(confd);
                Close(listenfd);
            }
            while((len=Read(confd,buf,MAXLINE))>0){
                fwrite(buf,sizeof(char),len,fp);
            }
            if(len==0){
                fclose(fp);
                printf("receive file done
    ");
                Close(confd);
            }
        }
        Close(listenfd);
        return 0;
    }

    wrap.c

    #include "wrap.h" 
    
    /********************************************************************* 
     * * Name      : perr_exit 
     * * Description    : exit the function 
     * * Input    : the error string        
     * * Output    :    
     * * Return    :    
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    void perr_exit(const char *s) 
    { 
        perror(s); 
        exit(1); 
    } 
    
    /********************************************************************* 
     * * Name      : Accept 
     * * Description    : accept a connection on a socket 
     * * Input    : fd---a socket that has been created     
     * * sa---a pointer to a sockaddr structure 
     * * salenptr---actual size of the peer address 
     * * Output    :    
     * * Return    : the descriptor for the accepted socket    
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr) 
    { 
        int n; 
    
    again: 
        if((n = accept(fd, sa, salenptr)) < 0) { 
            if((ECONNABORTED == errno) || (EINTR == errno)) 
                goto again; 
            else 
                perr_exit("accept error"); 
        } 
    
        return n; 
    } 
    
    /********************************************************************* 
     * * Name      : Bind 
     * * Description    : bind a name to a socket 
     * * Input    : fd---a socket that has been created     
     * * sa---a pointer to a sockaddr structure 
     * * salen---the size of the address structure 
     * * Output    :    
     * * Return    :    
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    void Bind(int fd, const struct sockaddr *sa, socklen_t salen) 
    { 
        if(bind(fd, sa, salen) < 0) 
            perr_exit("bind error"); 
    } 
    
    /********************************************************************* 
     * * Name      : Connect 
     * * Description    : initiate a connection on a socket 
     * * Input    : fd---a socket that has been created     
     * * sa---a pointer to a sockaddr structure 
     * * salen---the size of the address structure 
     * * Output    :    
     * * Return    :    
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    void Connect(int fd, const struct sockaddr *sa, socklen_t salen) 
    { 
        if(connect(fd, sa, salen) < 0) 
            perr_exit("connect error"); 
    } 
    
    /********************************************************************* 
     * * Name      : Listen 
     * * Description    : listen for connections on a socket 
     * * Input    : fd---a socket that has been created     
     * * backlog---the maximum length to the queue of 
     * * pending connections 
     * * Output    :    
     * * Return    :    
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    void Listen(int fd, int backlog) 
    { 
        if(listen(fd, backlog) < 0) 
            perr_exit("listen error"); 
    } 
    
    /********************************************************************* 
     * * Name      : Socket 
     * * Description    : create an endpoint for communication 
     * * Input    : family---a communication domain     
     * * type---the communication semantics 
     * * protocol---a particular protocol for the socket 
     * * Output    :    
     * * Return    : return a descriptor of the socket 
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    int Socket(int family, int type, int protocol) 
    { 
        int n; 
    
        if((n = socket(family, type, protocol)) < 0) 
            perr_exit("socket error"); 
        return n; 
    } 
    
    /********************************************************************* 
     * * Name      : Read 
     * * Description    : read from a file descriptor 
     * * Input    : fd---a socket that has been created     
     * * ptr---the buffer which storage the bytes    
     * * nbytes---the number of bytes read 
     * * Output    :    
     * * Return    : return the number of bytes read 
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    ssize_t Read(int fd, void *ptr, size_t nbytes) 
    { 
        ssize_t n; 
    
    again: 
        if((n = read(fd, ptr, nbytes)) == -1) { 
            if(EINTR == errno) 
                goto again; 
            else 
                return -1; 
        }    
    
        return n; 
    } 
    
    /********************************************************************* 
     * * Name      : Write 
     * * Description    : write to a file descriptor 
     * * Input    : fd---a socket that has been created     
     * * ptr---buffer of the bytes    
     * * nbytes---the number of bytes written 
     * * Output    :    
     * * Return    : return the number of bytes written 
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    ssize_t Write(int fd, const void *ptr, size_t nbytes) 
    { 
        ssize_t n; 
    
    again: 
        if((n = write(fd, ptr, nbytes)) == -1) { 
            if(EINTR == errno) 
                goto again; 
            else 
                return -1; 
        } 
    
        return n; 
    } 
    
    /********************************************************************* 
     * * Name      : Close 
     * * Description    : close a file descriptor 
     * * Input    : fd---a socket that has been created     
     * * Output    :    
     * * Return    :    
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    void Close(int fd) 
    { 
        if(close(fd) == -1) 
            perr_exit("close error");    
    } 
    
    /********************************************************************* 
     * * Name      : Readn 
     * * Description    : read from a file descriptor,    
     * * make sure read the enough bytes 
     * * Input    : fd---a socket that has been created     
     * * ptr---the buffer which storage the bytes    
     * * nbytes---the number of bytes read 
     * * Output    :    
     * * Return    : return the number of bytes read 
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    ssize_t Readn(int fd, void *vptr, size_t nbytes) 
    { 
        size_t nleft; 
        size_t nread; 
        char *ptr; 
    
        ptr = vptr; 
        nleft = nbytes; 
    
        while(nleft > 0) { 
            if((nread = read(fd, ptr, nleft)) < 0) { 
                if(EINTR == errno)     
                    nread = 0; 
                else 
                    return -1; 
            } else if(nread == 0) 
                break; 
    
            nleft -= nread; 
            ptr += nread; 
        } 
    
        return (nbytes-nleft); 
    } 
    
    /********************************************************************* 
     * * Name      : Writen 
     * * Description    : write to a file descriptor,    
     * * make sure write the enough bytes 
     * * Input    : fd---a socket that has been created     
     * * ptr---the buffer which storage the bytes    
     * * nbytes---the number of bytes read 
     * * Output    :    
     * * Return    : return the number of bytes read 
     * * Others    : by jzk 2009.12.02 
     * **********************************************************************/ 
    ssize_t Writen(int fd, const void *vptr, size_t nbytes) 
    { 
        size_t nleft; 
        size_t nwritten; 
        const char *ptr; 
    
        ptr = vptr; 
        nleft = nbytes; 
    
        while(nleft > 0) { 
            if((nwritten = write(fd, ptr, nleft)) <= 0) {    
                if(nwritten < 0 && EINTR == errno) 
                    nwritten = 0; 
                else 
                    return -1; 
            } 
    
            nleft -= nwritten; 
            ptr += nwritten; 
        } 
    
        return nbytes; 
    }
    
    static ssize_t my_read(int fd,char *ptr)
    {
        static int read_cnt;
        static char *read_ptr;
        static char read_buf[100];
    
        if(read_cnt<=0){
    again:
            if((read_cnt=read(fd,read_buf,sizeof(read_buf))<0)){
                if(errno==EINTR)
                    goto again;
                    return -1;
            }else if(read_cnt==0)
                return 0;
            read_ptr=read_buf;
        }
        read_cnt--;
        *ptr=*read_ptr++;
        return 1;
    }
    size_t Read_line(int fd,void *vptr,size_t maxlen)
    {
        ssize_t n,rc;
        char c,*ptr;
    
        ptr=vptr;
        for(n=1;n<maxlen;n++){
            if((rc=my_read(fd,&c))==1){
                *ptr++=c;
                if(c=='
    ')
                    break;
            }else if(rc==0){
                *ptr=0;
                return n-1;
            }else
                 return -1;
        }
        *ptr=0;
        return n;
    }

    wrap.h

    #ifndef WRAP_H 
    #define WRAP_H 
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h> 
    #include <unistd.h>
    #include <sys/socket.h> 
    
    void perr_exit(const char *s); 
    
    int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr); 
    void Bind(int fd, const struct sockaddr *sa, socklen_t salen); 
    void Connect(int fd, const struct sockaddr *sa, socklen_t salen); 
    void Listen(int fd, int backlog); 
    
    int Socket(int family, int type, int protocol); 
    void Close(int fd); 
    
    ssize_t Read(int fd, void *ptr, size_t nbytes); 
    ssize_t Write(int fd, const void *ptr, size_t nbytes); 
    
    ssize_t Readn(int fd, void *vptr, size_t n); 
    ssize_t Writen(int fd, const void *vptr, size_t n); 
    
    ssize_t Readline(int fd, void *vptr, size_t maxlen); 
    
    #endif 

    Makefile

    ######################################
    #
    #######################################
    #source file
    #源文件,自动找所有.c和.cpp文件,并将目标定义为同名.o文件
    SOURCE  := $(wildcard *.c) $(wildcard *.cpp)
    OBJS    := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE)))
    
    #target you can change test to what you want
    #目标文件名,输入任意你想要的执行文件名
    TARGET  := client server 
    APP1    := client
    APP2    := server
    
    MAINS    :=$(APP1).o $(APP2).o
    #compile and lib parameter
    #编译参数
    CC      := gcc
    LIBS    := -lpthread -lrt
    LDFLAGS :=
    DEFINES :=
    INCLUDE := -I.
    CFLAGS  := -g -Wall -O3 $(DEFINES) $(INCLUDE)
    CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H
    
    #i think you should do anything here
    #下面的基本上不需要做任何改动了
    .PHONY : everything objs clean veryclean rebuild
    
    everything : $(TARGET)
    
    all : $(TARGET)
    
    objs : $(OBJS)
    
    rebuild: veryclean everything
    
    clean :
        rm -fr *.so
        rm -fr *.o
    
    veryclean : clean
        rm -fr $(TARGET)
    
    $(APP1) :$(APP1).o $(filter-out $(MAINS), $(OBJS))
        $(CC)  $(CXXFLAGS) -o $@ $^  $(LDFLAGS) $(LIBS)
    $(APP2) :$(APP2).o $(filter-out $(MAINS), $(OBJS))
        $(CC)  $(CXXFLAGS) -o $@ $^  $(LDFLAGS) $(LIBS)
  • 相关阅读:
    P3396 哈希冲突
    P3295 [SCOI2016]萌萌哒
    P2585 [ZJOI2006]三色二叉树
    Leetcode 1546 和为目标值的最大数目不重叠非空子数组数目 贪心前缀和
    Leetcode 200 岛屿数量 压缩路径并查集与DFS
    Leetcode 递增子序列 回溯去重
    机器学习sklearn(76):算法实例(三十三)回归(五)线性回归大家族(三)回归类的模型评估指标
    机器学习sklearn(75):算法实例(三十二)回归(四)线性回归大家族(二)多元线性回归LinearRegression
    机器学习sklearn(74):算法实例(三十一)回归(三)线性回归大家族(一)概述
    机器学习sklearn(73):算法实例(三十)分类(十七)SVM(八)sklearn.svm.SVC(七) SVC真实数据案例:预测明天是否会下雨
  • 原文地址:https://www.cnblogs.com/tla001/p/6670412.html
Copyright © 2020-2023  润新知