Linux平台基于socket的文件传输服务器和客户端
生活随笔
收集整理的這篇文章主要介紹了
Linux平台基于socket的文件传输服务器和客户端
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Linux平臺基于socket的文件傳輸服務器和客戶端
目錄
- 前言
- 一、服務器程序結構
- 二、客戶程序結構
- 三、代碼
- 1.服務器主程序video_serv_fork.c
- 2.服務器子程序video_trans.c
- 3.客戶主程序video_cli.c
- 4.客戶字程序video_trans_cli.c
前言
說些廢話,本來讓寫網絡視頻傳輸服務,結果除了視頻,所有文件都可以進行傳輸。還好,畢竟文件傳輸原理是一樣的,讀取二進制流,傳輸二進制流,寫入二進制流。
一、服務器程序結構
采用fork()派生子進程來處理和客戶的文件傳輸。主進程只負責監聽。有兩個文件video_serv_fork.c和video_trans.c,分別是主程序和子程序文件。
二、客戶程序結構
采用select內核函數實現左顧右盼能力,同時監聽標準輸入和套接口。有兩個文件video_cli.c和video_trans_cli.c,分別是主程序和子程序文件。
三、代碼
1.服務器主程序video_serv_fork.c
代碼如下:
#include <unp.h>#define FILE_NAME_MAX_SIZE 1024 #define BUFFER_SIZE 1024 #define MAX_FILE 1024void video_trans(int sockfd, char *buf);void sig_chld(int signo) {pid_t pid;int stat;while((pid = waitpid(-1, &stat, WNOHANG)) > 0)printf("child %d terminated\n", pid);return; }int main(int argc, char ** argv) {pid_t childpid;int n, listenfd, connfd;char buf[MAX_FILE];socklen_t clilen;struct sockaddr_in cliaddr, servaddr;listenfd = Socket(AF_INET, SOCK_STREAM, 0);//創建IPV4套接口bzero(&servaddr, sizeof(servaddr));//設置地址結構體servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));//套接口上綁定地址Listen(listenfd, LISTENQ);//開始監聽Signal(SIGCHLD, sig_chld);//聲明需要捕獲子進程信號for( ; ; ){clilen = sizeof(cliaddr);if((connfd = accept(listenfd, (SA *)&cliaddr, &clilen)) < 0)//建立連接{if(errno == EINTR)//慢系統調用continue;else{printf("errno = %d,",errno);err_sys("accept error\n");}}if((childpid = Fork()) == 0)//派生子進程{Close(listenfd);if ((n = recv(connfd, buf, MAXLINE, 0)) == 0)//沒有接收到任何字符{printf("please input correct file name\n");}else{video_trans(connfd, buf);}exit(0);}Close(connfd);} }2.服務器子程序video_trans.c
代碼如下:
#include <unp.h>#define FILE_NAME_MAX_SIZE 1024 #define BUFFER_SIZE 1024 #define MAX_FILE 1024void video_trans(int sockfd, char *buf) {int flag;//發送是否成功標志char file_name[FILE_NAME_MAX_SIZE + 1];//文件名數組FILE *fp;//文件指針char *b = (char *)malloc(sizeof(char));//讀取二進制文件塊指針bzero(file_name, sizeof(file_name));printf("the client needs: %s ", buf);char * find = strchr(buf, '\n');//剔除文件名的回車if(find)*find = '\0';strncpy(file_name, buf, strlen(buf) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buf));fp = fopen(file_name, "rb+");//二進制方式打開file_name文件if(fp == NULL){printf("%s :", file_name);perror("File Not Found\n");}else{bzero(buf, sizeof(buf));flag = 1;printf("\nsending file: %s ......\n", file_name);while(!feof(fp))//文件不為空{fread(b, 1, 1, fp);//從fp文件指針所指的文件中每次讀取1個字節的二進制串,讀1次放入b指針printf("%d ", *b);//打印讀取到的內容if(send(sockfd, b, 1, 0) < 0)//給sockfd把b二進制串發送過去{printf("Failed To Send File: %s ", file_name);printf("\n");flag = 0;}}bzero(buf, sizeof(buf));}fclose(fp);if(flag == 1){printf("\nSuccess To send File: %s", file_name);printf("\n");}}3.客戶主程序video_cli.c
代碼如下:
#include <unp.h>#define FILE_NAME_SIZE 1024 #define BUFFER_SIZE 1024void trans(FILE *fp, int sockfd, char *file_name, char **argv);int main(int argc, char **argv) {int sockfd;struct sockaddr_in servaddr;char file_name[FILE_NAME_SIZE];if(argc != 2)err_quit("用法: video_cli <IPaddress>\n");sockfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr) == 0){err_quit("服務器地址錯誤!\n");}if(connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0){printf("無法連接到服務器 %s!\n", argv[1]);exit(1);}printf("請輸入文件名稱(如存在請先刪除):\n");trans(stdin, sockfd, file_name, argv);exit(0); }4.客戶字程序video_trans_cli.c
代碼如下:
#include <unp.h>#define FILE_NAME_SIZE 1024 #define BUFFER_SIZE 1024void trans(FILE *fp, int sockfd, char *file_name, char **argv) {int maxfdp1, stdineof = 0, length = 1;fd_set rset;char buf[BUFFER_SIZE];FILE *f;char *b = (char *)malloc(sizeof(char));//寫入文件block指針FD_ZERO(&rset);bzero(file_name, sizeof(file_name));bzero(buf, sizeof(buf));for ( ; ; ){if(stdineof == 0){FD_SET(fileno(fp), &rset);}FD_SET(sockfd, &rset);maxfdp1 = max(fileno(fp), sockfd) + 1;Select(maxfdp1, &rset, NULL, NULL, NULL);if(FD_ISSET(fileno(fp), &rset)){if(fgets(file_name, FILE_NAME_SIZE, fp) == NULL)// 從標準輸入讀取文件名{stdineof = 1;Shutdown(sockfd, SHUT_WR);FD_CLR(fileno(fp), &rset);continue;}else{char * find = strchr(file_name, '\n');if(find)*find = '\0';// 文件名稱存入bufstrncpy(buf, file_name, strlen(file_name) > BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name));// 向服務器發送buf數據,此時buf中存放的是客戶端需要接受的文件名字send(sockfd, buf, BUFFER_SIZE, 0);}}if(FD_ISSET(sockfd, &rset)){bzero(buf, sizeof(buf)); f = fopen(file_name, "wb+");if(f == NULL){printf("文件: %s 無法打開并寫入!\n", file_name);exit(1);}// 從服務器接收內容到buf while((length= recv(sockfd, b, 1, 0)) >= 0){if(length == 0){if(stdineof == 1)return;else{printf("\n從服務器 %s 接收到文件: %s\n", argv[1], file_name);//err_quit("服務器已終止\n");return;} }if(length > 0){printf("%d ", *b);fwrite(b, 1, 1, f); }}fclose(f);}} }總結
以上是生活随笔為你收集整理的Linux平台基于socket的文件传输服务器和客户端的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c# https请求忽略证书验证_c#
- 下一篇: 安徽 省二级计算机笔试真题,安徽省计算机