linux socket c/s上传文件

Posted 悠悠南山下

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\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 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\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    := 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 [email protected] $^  $(LDFLAGS) $(LIBS)
$(APP2) :$(APP2).o $(filter-out $(MAINS), $(OBJS))
    $(CC)  $(CXXFLAGS) -o [email protected] $^  $(LDFLAGS) $(LIBS)

 

以上是关于linux socket c/s上传文件的主要内容,如果未能解决你的问题,请参考以下文章

Java编程基础之网络编程

第六章 网络编程-SOCKET开发

socket 上传文件代码

java Ftp上传创建多层文件的代码片段

实现Linux select IO复用C/S服务器代码

C语言socket网络编程