getfile
實現 | getfile <ipaddr> <source filename> <destination filename> |
例如 | ./getfile 127.0.0.1 /etc/passwd passwd |
顯示 | 成功 GET Success (12345 bytes) 失敗 Error! |
參考 | ch7/file ch7/wrapper/tcputils.c |
/* Server*/ #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <fcntl.h> #include <string.h> #include <stdio.h> #include "copy.h" #include "tcputils.h" #define BUFFER_LENGTH 128 int main() { int server_sockfd, client_sockfd; socklen_t client_len; struct sockaddr_in client_address; // Open a socket for the server. server_sockfd=open_sock(9735); while(1) { char buf[BUFFER_LENGTH]; int fd; int size; printf("server waiting\n"); /* Accept a connection. */ client_len = sizeof(client_address); client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len); int res; // Get filename from client res = read(client_sockfd, buf, BUFFER_LENGTH); printf("Filename from client %s\n", buf); size = 0; // Open source file fd = open(buf,O_RDONLY); if (fd < 0) // File not found { buf[0] = '0'; write(client_sockfd, buf, 1); } else { buf[0] = '1'; write(client_sockfd, buf, 1); // Start to copy file size = copy_file(fd,client_sockfd); if( size > 0 ) { printf("write size = %d\n", size); } else { perror("size"); } } close(fd); close(client_sockfd); } }
/* Client */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <fcntl.h> #include "copy.h" #include "tcputils.h" int main(int argc, char* argv[]) { int sockfd; int fd; int size; char bResult; // Check parameters, I add a new parameter for destination filename. if (argc != 4) { printf("Usage: getfile <ipaddr> <source filename> <destination filename>\n"); exit(EXIT_SUCCESS); } // Create a socket for the client. sockfd=open_clientsock(argv[1],9735); int res; // Send source filename to server res = write(sockfd, argv[2], strlen(argv[2])+1); // Get server response res = read(sockfd, &bResult, 1); if (bResult == '1') // Server is ready to send file { size = 0; // Create destination file fd = open(argv[3],O_WRONLY|O_CREAT,0666); if (fd < 0) // create file error { perror("client:"); } // Copy file size=copy_file(sockfd,fd); printf("GET Success (%d bytes)\n", size); close(fd); } else { printf("Error!\n"); } close(sockfd); exit(EXIT_SUCCESS); }
程式說明如下:
- Server 端開啟 Socket Port 9735 後即等待 Client 端連線
- Client 端開啟 Socket 後請求連線
- Client 端先傳來源檔名給 Server 端檢查檔案是否存在
- Server 端若檢查成功則傳回 1,開啟來源檔案準備複製;若檢查失敗則傳回 0,結束連線
- Client 若收到成功訊息,則開啟目的檔案開始複製,並列印複製成功與檔案大小;若收到失敗訊息,則直接列印錯誤訊息,結束連線
執行結果如下:
注意事項:
在取得 Server 端回應時,我原本的寫法如下:
res = read(sockfd, buf, 128);
當 Server 端傳回 "OK" 時,後續傳回來的檔案卻少了 125 Bytes。原來我在讀回應時,總共讀了 128 Bytes,其中 3 Bytes 為 "OK" 加上結束字元,而 125 Bytes 則為檔案的內容。這也驗證了老師提到處理 Buffer 要特別注意的地方,因為 Server 回應與檔案傳輸已經合併傳送了。
延伸功能:
- ipaddr 參數改成支援 URL
- 利用 fork() 支援多個檔案同時傳輸
- 修改為 Nonblocking I/O 的方式
留言