linuxC socket 發送和接收檔案小例子

來源:互聯網
上載者:User

LINUX C 基於TCP/IP協議的SOCKET收發檔案的小例子。

自已沒事正看這方面的東西,感覺要想把網路這塊弄明白還真不是件簡單的事。

程式寫的比較繁瑣,代碼也不合理,有時間再把程式最佳化一下,加上斷點繼傳的功能。。

伺服器端:
/******** http://blog.csdn.net/robertkun ********//*******  伺服器程式  (server.c)     ************/// linux 下讀取大於2GB檔案時,需指定#define _FILE_OFFSET_BITS 64#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <arpa/inet.h>#include <fcntl.h>// 定義包的大小為512KB#define PACK_SIZE 1024*512int main(int argc, char *argv[]){// 設定輸出緩衝setvbuf(stdout, NULL, _IONBF, 0);fflush(stdout);int sockfd,new_fd;struct sockaddr_in server_addr;struct sockaddr_in client_addr;int sin_size,portnumber;char hello[]="Hello! Are You Fine?\n";if((portnumber=atoi("8080"))<0){fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);exit(1);}/* 伺服器端開始建立socket描述符 */if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {fprintf(stderr,"Socket error:%s\n\a",strerror(errno));exit(1);}/* 伺服器端填充 sockaddr結構  */bzero(&server_addr,sizeof(struct sockaddr_in));server_addr.sin_family=AF_INET;server_addr.sin_addr.s_addr=htonl(INADDR_ANY);server_addr.sin_port=htons(portnumber);/* 捆綁sockfd描述符  */if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) {fprintf(stderr,"Bind error:%s\n\a",strerror(errno));exit(1);}/* 監聽sockfd描述符  */if(listen(sockfd,5)==-1) {fprintf(stderr,"Listen error:%s\n\a",strerror(errno));exit(1);}while(1){fprintf(stderr, "server is listening!\n");/* 伺服器阻塞,直到客戶程式建立串連  */sin_size=sizeof(struct sockaddr_in);if( ( new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),(socklen_t*)&sin_size ) ) == -1) {fprintf(stderr,"Accept error:%s\n\a",strerror(errno));exit(1);}fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr));if(write(new_fd,hello,strlen(hello))==-1) {fprintf(stderr,"Write Error:%s\n",strerror(errno));exit(1);}long int read_size = 0;unsigned long file_len  = 0;int order_id  = 0;char file_name[128] = {'\0'};char file_info[1024] = {'\0'};// 讀取指令printf("\n\nWaiting for read file info!\n");int nn = 0;if(nn = read(new_fd, file_info, 1024)) {// 指令IDint id_h = (int)file_info[0]<<8;order_id = id_h + (int)file_info[1];// 檔案長度// 高16位unsigned long len_hig_1 = 0;memcpy(&len_hig_1, &file_info[2], sizeof(file_info[2]));unsigned long len_hig_2 = 0;memcpy(&len_hig_2, &file_info[3], sizeof(file_info[3]));unsigned long len_hig = len_hig_1 * 256 + len_hig_2;// 低16位unsigned long len_low_1 = 0;memcpy(&len_low_1, &file_info[4], sizeof(file_info[4]));unsigned long len_low_2 = 0;memcpy(&len_low_2, &file_info[5], sizeof(file_info[5]));int len_low = len_low_1 * 256 + len_low_2;file_len = len_hig * 256 * 256 + len_low;// 檔案名稱strncpy(file_name, &file_info[6], strlen(&file_info[6]));printf("order = %d, %lu, %s\n", order_id, file_len, file_name);if((strlen(file_name) == 0) || (file_len == 0)){printf("Read file info error!\n File_name or file_len is zero!\n");close(new_fd);continue;}}else {printf("Read file info error!\n");close(new_fd);close(sockfd);exit(0);}// 寫入檔案printf("\n\nWaiting for read file content!\n");FILE* pf = fopen(file_name, "wb+");if(pf == NULL){printf("Open file error!\n");close(new_fd);continue;}char buff[PACK_SIZE] = {'\0'};while(read_size <= file_len) {//bzero(buff, 1024);int rlen = read(new_fd, buff, PACK_SIZE);if(rlen) {//system("clear");printf("\n\nRead package size = %d\n", rlen);int wn = fwrite(buff, sizeof(char), rlen, pf);read_size += rlen;printf("write file size = %d\n", wn);//printf("Read  total  size = %d\n", read_size);}else {printf("Read over!...%d\n", rlen);break;}} // End Whileprintf("File len = %ld ... Already read size = %ld\n", file_len, read_size);/* 這個通訊已經結束     */fclose(pf);close(new_fd);/* 迴圈下一個     */}close(sockfd);exit(0);}
用戶端:
/******** http://blog.csdn.net/robertkun ********//******* 用戶端程式  client.c        ************/// linux 下讀取大於2GB檔案時,需指定#define _FILE_OFFSET_BITS 64#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <arpa/inet.h>#include <sys/stat.h>#include <fcntl.h>// 檔案讀寫// 定義包的大小為512KB#define PACK_SIZE 1024*512char* get_file_name(char* fn);unsigned long get_file_size(const char *path);int main(int argc, char *argv[]){if(argc < 2){printf("please input:<ip> <port> <filePath>.\n");return 0;}        // 設定輸出緩衝        setvbuf(stdout, NULL, _IONBF, 0);        fflush(stdout);char* filePath = argv[3];if(access(filePath, F_OK) != 0){printf("file not existed!\n");return 0;}        int sockfd;        char buff[1024] = {'\0'};        struct sockaddr_in server_addr;        struct hostent *host;        int portnumber,nbytes;const char* ip = argv[1];        if((host=gethostbyname(ip))==NULL)        {                fprintf(stderr,"Gethostname error\n");                exit(1);        }const char* port = argv[2];        if((portnumber=atoi(port))<0)        {                fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);                exit(1);        }        /* 客戶程式開始建立 sockfd描述符  */        if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)        {                fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));                exit(1);        }        /* 客戶程式填充服務端的資料       */        bzero(&server_addr,sizeof(server_addr));        server_addr.sin_family=AF_INET;        server_addr.sin_port=htons(portnumber);        server_addr.sin_addr=*((struct in_addr *)host->h_addr);        /* 客戶程式發起串連請求         */        if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)        {                fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));                exit(1);        }        /* 串連成功了           */        if((nbytes=read(sockfd,buff,1024))==-1)        {                fprintf(stderr,"Read Error:%s\n",strerror(errno));                exit(1);        }        buff[nbytes]='\0';        printf("I have received:%s\n",buff);/******* 發送指令 ********/bzero(buff,1024);// 指令IDint order = 0x0010;int order_h = order >> 8;buff[0] = (char)order_h;buff[1] = (char)order;// 檔案長度unsigned long len = get_file_size(filePath);printf("file size = %lu\n", len);// 高16位int len_h = len >> 16;int len_h_1 = len_h >> 8;buff[2] = (char)len_h_1;buff[3] = (char)len_h;// 低16位int len_l = len;int len_l_1 = len_l >> 8;buff[4] = (char)len_l_1;buff[5] = (char)len_l;// 檔案名稱char* fileName = get_file_name(filePath);printf("file name = %s\n", fileName);strncpy(&buff[6], fileName, strlen(fileName));write(sockfd,buff,1024); /******* 傳送檔案 ********/printf("file path = %s\n", filePath);FILE* pf = fopen(filePath, "rb");if(pf == NULL) {printf("open file failed!\n");exit(0);}char pack[PACK_SIZE] = {'\0'};while((len = fread(pack, sizeof(char), PACK_SIZE, pf)) > 0)    {system("clear");printf("send data size = %d \t", len);write(sockfd, pack, len);bzero(pack,PACK_SIZE);//sleep(1);    }        /* 結束通訊     */        close(sockfd);        exit(0);}char* get_file_name(char* fn){int last = 0;char* pfn = fn+strlen(fn)-1;int i=0;for(i=0; i<strlen(fn); ++i){if(*pfn-- == '/'){last = strlen(fn)-i;break;}}char* name = (char*)malloc(sizeof(char)*256);char* pname = name;int j=0;for(j=last; j<strlen(fn); ++j, ++pname){*pname = fn[j];}return name;}unsigned long get_file_size(const char *path){unsigned int filesize = 0;struct stat statbuff;if(stat(path, &statbuff) < 0) {printf("Get file stat failed!\n");return filesize;}else{filesize = statbuff.st_size;}return filesize;}

MAKEFILE:

伺服器端:

object=server.oserver.o:        gcc -g -c server.c        gcc -o server $(object)clean:        rm server $(object)

用戶端:

object=client.oclient.o:        gcc -g -c client.c        gcc -o client $(object)clean:        rm -rf client $(object)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.