日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于TCP/IP的文件服务器编程一例

發布時間:2023/12/2 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于TCP/IP的文件服务器编程一例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

來源,華清遠見嵌入式學院實驗手冊,代碼來源:華清遠見曾宏安

實現的功能:

編寫TCP文件服務器和客戶端。客戶端可以上傳和下載文件

客戶端支持功能如下:

1.支持一下命令

help 顯示客戶端所有命令和說明

list? 顯示服務器端可以下載的文件列表

get <filename> 下載文件

put <filename> 上傳文件

quit 退出客戶端

?

服務器端功能(單進程)

解析客戶端的命令并提供相應的服務

?

服務器流程:

?

?

?

服務器端的代碼:

1: #include <stdio.h> 2: #include <stdlib.h> 3: #include <unistd.h> 4: #include <string.h> 5: #include <fcntl.h> 6: #include <dirent.h> 7: #include <sys/socket.h> 8: #include <netinet/in.h> 9: #include <arpa/inet.h> 10: ? 11: #define N 256 12: ? 13: typedef struct sockaddr SA; // 14: ? 15: void do_list(int connfd) 16: { 17: DIR *mydir; 18: struct dirent *dp; 19: ? 20: if ((mydir = opendir(".")) == NULL) //打開當前目錄 21: { 22: perror("fail to opendir"); 23: return; 24: } 25: while ((dp = readdir(mydir)) != NULL) //讀目錄,每次返回一項, 讀完時,返回空 26: { 27: if (dp->d_name[0] != '.') //將.和..以及隱藏文件跳過 28: { 29: send(connfd, dp->d_name, N, 0); //為了便于客戶端將每次發送的目錄項區分開,服務器每次發N個,相應的客戶端也受N個 30: } 31: } 32: closedir(mydir); //關閉目錄 33: } 34: ? 35: void do_get(int connfd, char fname[]) //下載請求處理函數 36: { 37: int fd, nbyte; 38: char buf[N]; 39: ? 40: if ((fd = open(fname, O_RDONLY)) < 0) //以只讀方式打開,假如不存在,報錯 41: { 42: perror("fail to open"); 43: send(connfd, "N", 1, 0); //向客戶端發送‘N',表示文件不存在,發送1個,客戶端也收1個 44: return; 退出下載請求處理函數,注:服務器不能退出 45: } 46: send(connfd, "Y", 1, 0); //向客戶端發送Y,表示文件存在 47: while ((nbyte = read(fd, buf, N)) > 0) //讀文件,讀完了返回空 48: { 49: send(connfd, buf, nbyte, 0); //發送文件原則:讀多少,就發多少! 50: } 51: close(fd); 52: } 53: ? 54: void do_put(int connfd, char fname[]) //上傳請求處理函數 55: { 56: int fd, nbyte; 57: char buf[N]; 58: ? 59: if ((fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0666)) < 0) //不存在創建,存在報錯 60: { 61: perror("fail to open"); 62: send(connfd, "N", 1, 0); //向客戶端發送‘N',表示文件已存在,發送1個,客戶端也收1個 63: return; 64: } 65: send(connfd, "Y", 1, 0);//向客戶端發送‘N',表示文件不存在,可以上傳。發送1個,客戶端也收1個 66: while ((nbyte = recv(connfd, buf, N, 0)) > 0) 67: { 68: write(fd, buf, nbyte); //寫文件原則:接收多少,就寫多少 69: } 70: close(fd); 71: } 72: ? 73: int main(int argc, char *argv[]) 74: { 75: int listenfd, connfd; 76: char command[N]; 77: struct sockaddr_in myaddr, peeraddr; 78: socklen_t peerlen = sizeof(peeraddr); 79: ? 80: if (argc < 3) 81: { 82: printf("Usage : %s <ip> <port>\n", argv[0]); 83: return -1; 84: } 85: ? 86: // XXX int socket(int domain, int type, int protocol); 87: if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) 88: { 89: perror("fail to socket"); 90: exit(-1); 91: } 92: ? 93: bzero(&myaddr, sizeof(myaddr)); 94: myaddr.sin_family = PF_INET; 95: myaddr.sin_port = htons(atoi(argv[2])); 96: myaddr.sin_addr.s_addr = inet_addr(argv[1]); 97: // XXX int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 98: if (bind(listenfd, (SA *)&myaddr, sizeof(myaddr)) < 0) 99: { 100: perror("fail to bind"); 101: exit(-1); 102: } 103: ? 104: if (listen(listenfd, 5) < 0) 105: { 106: perror("fail to listen"); 107: exit(-1); 108: } 109: ? 110: while ( 1 ) 111: { 112: // XXX int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 113: if ((connfd = accept(listenfd, (SA *)&peeraddr, &peerlen)) < 0) 114: { 115: perror("fail to accept"); 116: exit(-1); 117: } 118: printf("connection from [%s:%d]\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port)); 119: recv(connfd, command, N, 0); // recv command from client,簡單處理,客戶端發N個,服務器也應該收N個 120: switch ( command[0] ) //因為客戶端發來的命令第一個字符就是命令類型 121: { 122: case 'L': //客戶端的列表請求 123: printf("do_list\n"); 124: do_list(connfd); 125: break; 126: case 'G': //客戶端的下載請求 127: do_get(connfd, command+1); 128: break; 129: case 'P': //客戶端的上傳請求 130: do_put(connfd, command+1); 131: break; 132: } 133: close(connfd); //關閉本次的連接套接字 134: } 135: ? 136: return 0; 137: }

?客戶端流程:

?

客戶端的代碼:

1: #include <stdio.h> 2: #include <stdlib.h> 3: #include <unistd.h> 4: #include <string.h> 5: #include <fcntl.h> 6: #include <sys/socket.h> 7: #include <netinet/in.h> 8: #include <arpa/inet.h> 9: ? 10: #define N 256 11: ? 12: typedef struct sockaddr SA; 13: ? 14: void do_help() 15: { 16: printf(" help : display help info\n"); 17: printf(" list : get file list from server\n"); 18: printf("get <file> : download <file> from server\n"); 19: printf("put <file> : upload <file> to server\n"); 20: printf(" quit : exit\n"); 21: } 22: ? 23: void do_list(struct sockaddr_in servaddr) //list命令處理函數 24: { 25: int sockfd; 26: char buf[N]; 27: ? 28: if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) 29: { 30: perror("fail to socket"); 31: exit(-1); 32: } 33: ? 34: // XXX int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 35: if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) 36: { 37: perror("fail to connect"); 38: exit(-1); 39: } 40: 41: buf[0] = 'L'; //向服務器發送字符'L',表示list命令 42: send(sockfd, buf, N, 0); // send command to server,發送字節數N最好與服務器那邊對應起來,發多少,收多少 43: while (recv(sockfd, buf, N, 0) > 0) //簡單處理,服務器每次發N個,那么客戶端每次也應該收N個,這樣就把每個目錄項區分開了 44: { 45: printf(" %s\n", buf); 46: } 47: close(sockfd); //關閉套接字 48: } 49: ? 50: void do_get(struct sockaddr_in servaddr, char fname[]) //下載處理函數 51: { 52: int sockfd, fd, nbyte; 53: char buf[N]; 54: ? 55: if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) 56: { 57: perror("fail to socket"); 58: exit(-1); 59: } 60: ? 61: // XXX int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 62: if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) 63: { 64: perror("fail to connect"); 65: exit(-1); 66: } 67: ? 68: sprintf(buf, "G%s", fname); //將上傳標識符'G'和文件名格式化輸出到緩沖區buf中,想法很好! 69: send(sockfd, buf, N, 0); // send command to server //將客戶端的上傳命令連同文件名一塊發給服務器。 70: //等待服務器的確認回復,因為要下載的文件名可能在服務器上不存在,服務器發送了1個,所以客戶端也應該接收至少1個。 71: recv(sockfd, buf, 1, 0); // recv reply from server 72: if (buf[0] == 'N') //服務器返回N,說明服務器上沒有客戶端要下載的文件 73: { 74: printf("can't open %s on server\n", fname); 75: close(sockfd); //關閉套接字 76: return; //退出下載處理函數 77: } 78: if ((fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) //不存在創建,存在清除 79: { 80: perror("fail to open"); 81: close(sockfd); 82: return; 83: } 84: while ((nbyte = recv(sockfd, buf, N, 0)) > 0) //接收服務器發送的文件內容 85: { 86: write(fd, buf, nbyte); //寫文件原則:收多少,就寫到少! 87: } 88: close(fd); //關閉文件描述符 89: close(sockfd); 90: } 91: ? 92: void do_put(struct sockaddr_in servaddr, char fname[]) //上傳處理函數 93: { 94: int sockfd, fd, nbyte; 95: char buf[N]; 96: ? 97: if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) 98: { 99: perror("fail to socket"); 100: exit(-1); 101: } 102: ? 103: // XXX int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 104: if (connect(sockfd, (SA *)&servaddr, sizeof(servaddr)) < 0) 105: { 106: perror("fail to connect"); 107: exit(-1); 108: } 109: ? 110: sprintf(buf, "P%s", fname);//將下載標識符'P'和文件名格式化輸出到緩沖區buf中,想法很好! 111: send(sockfd, buf, N, 0); // send command to server//將客戶端的下載命令連同文件名一塊發給服務器。 112: //等待服務器的確認回復,因為要上傳的文件名可能在服務器上已經存在。服務器發送了1個,所以客戶端也應該接收至少1個。 113: recv(sockfd, buf, 1, 0); // recv reply from server 114: if (buf[0] == 'N') //服務器返回N,說明服務器上有客戶端要上傳的文件 115: { 116: printf("%s exsit on server,\n", fname); 117: close(sockfd); 118: return; 119: } 120: if ((fd = open(fname, O_RDONLY)) < 0) 121: { 122: perror("fail to open"); 123: close(sockfd); 124: return; 125: } 126: while ((nbyte = read(fd, buf, N)) > 0) 127: { 128: send(sockfd, buf, nbyte,0); //發送文件原則:從文件流中讀多少,就向服務器發多少! 129: } 130: close(fd); 131: close(sockfd); 132: } 133: ? 134: int main(int argc, char *argv[]) 135: { 136: int sockfd; 137: char command[N]; 138: struct sockaddr_in servaddr; 139: ? 140: if (argc < 3) 141: { 142: printf("Usage : %s <ip> <port>\n", argv[0]); 143: return -1; 144: } 145: ? 146: bzero(&servaddr, sizeof(servaddr)); 147: servaddr.sin_family = PF_INET; 148: servaddr.sin_port = htons(atoi(argv[2])); 149: servaddr.sin_addr.s_addr = inet_addr(argv[1]); 150: ? 151: #if 0 152: // XXX int socket(int domain, int type, int protocol); 153: #endif 154: while ( 1 ) 155: { 156: printf("client > "); 157: fgets(command, N, stdin); 158: command[strlen(command)-1] = '\0'; //將'\0'前面的'\n'用'\0'覆蓋。 159: if (strncmp(command, "help", 4) == 0) 160: { 161: do_help(); 162: } 163: else if (strncmp(command, "list", 4) == 0) 164: { 165: do_list(servaddr); 166: } 167: else if (strncmp(command, "get", 3) == 0) 168: { 169: do_get(servaddr, command+4); 170: } 171: else if (strncmp(command, "put", 3) == 0) 172: { 173: do_put(servaddr, command+4); 174: } 175: else if (strncmp(command, "quit", 4) == 0) 176: { 177: printf("bye\n"); 178: exit(0); 179: } 180: else 181: { 182: printf(" invalid command %s\n", command); 183: do_help(); 184: } 185: } 186: ? 187: return 0; 188: }

轉載于:https://www.cnblogs.com/pengdonglin137/archive/2013/03/13/2958192.html

總結

以上是生活随笔為你收集整理的基于TCP/IP的文件服务器编程一例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。