首页 > 代码库 > linux socket c/s上传文件

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 64struct 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\n",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 64struct 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\n",            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\n",file_name.len);            printf("file name is %s\n",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\n");            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==\n)                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    := clientAPP2    := serverMAINS    :=$(APP1).o $(APP2).o#compile and lib parameter#编译参数CC      := gccLIBS    := -lpthread -lrtLDFLAGS :=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 rebuildeverything : $(TARGET)all : $(TARGET)objs : $(OBJS)rebuild: veryclean everythingclean :    rm -fr *.so    rm -fr *.overyclean : 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)

 

linux socket c/s上传文件