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 的方式



留言