利用TCP完成檔案傳輸的設計和實現
阿新 • • 發佈:2019-02-11
實驗課的內容,建立tcp 實現檔案的傳輸,需要注意的一個地方就是,客戶端和伺服器端不要放在一起,檔案可以放在客戶端,絕對路徑就可以。還有就是自己寫一個makefile
服務端:
建立socket
使用bind繫結套接字
使用listen監聽
使用accept接受連線請求 accept返回新的套接字描述符
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define PORT 8789 /*偵聽埠地址*/ #define BACKLOG 2 /*偵聽佇列長度*/ int main(int argc, char *argv[]) { int ss,sc; /*ss為伺服器的socket描述符,sc為客戶端的socket描述符*/ struct sockaddr_in server_addr; /*伺服器地址結構*/ struct sockaddr_in client_addr; /*客戶端地址結構*/ int err; /*返回值*/ pid_t pid; /*分叉的進行ID*/ /*建立一個流式套接字*/ ss = socket(AF_INET, SOCK_STREAM, 0); if(ss < 0){ /*出錯*/ printf("socket error\n"); return -1; } /*設定伺服器地址*/ bzero(&server_addr, sizeof(server_addr)); /*清零*/ server_addr.sin_family = AF_INET; /*協議族*/ server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*本地地址*/ server_addr.sin_port = htons(PORT); /*伺服器埠*/ /*繫結地址結構到套接字描述符*/ err = bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr)); if(err < 0){/*出錯*/ printf("bind error\n"); return -1; } /*設定偵聽*/ err = listen(ss, BACKLOG); if(err < 0){ /*出錯*/ printf("listen error\n"); return -1; } /*主迴圈過程*/ for(;;) { socklen_t addrlen = sizeof(struct sockaddr); sc = accept(ss, (struct sockaddr*)&client_addr, &addrlen); /*接收客戶端連線*/ if(sc < 0){ /*出錯*/ continue; /*結束本次迴圈*/ } /*建立一個新的程序處理到來的連線*/ pid = fork(); /*分叉程序*/ if( pid == 0 ){ /*子程序中*/ process_conn_server(sc); /*處理連線*/ close(ss); /*在子程序中關閉伺服器的偵聽*/ return 0; }else{ close(sc); /*在父程序中關閉客戶端的連線*/ } } }
#include <stdio.h> #include <string.h> #define BUFFER_SIZE 1024 /*伺服器對客戶端的處理*/ void process_conn_server(int s) { ssize_t size = 0; char buffer[BUFFER_SIZE]; FILE *stream; strcpy(buffer,"請輸入傳輸的檔案路徑:\n"); write(s, buffer, BUFFER_SIZE); int length=0; char buffer_add[BUFFER_SIZE]={'\0'}; for(;;){ size = read(s, buffer, BUFFER_SIZE-length); if(size <= 0){ return; } strcat(buffer_add, buffer); length+=size; if(length>=BUFFER_SIZE) break; } if((stream=fopen(buffer_add, "w"))==NULL) return; for(;;){ size = read(s, buffer, BUFFER_SIZE); if(size <= 0){ return; } int write_len=fwrite(buffer, sizeof(char), size, stream); } fclose(stream); }
客戶端:
建立socket
確定伺服器scokaddr_in結構體 點分十進位制IP轉換
使用connect連線 開啟檔案
準備緩衝區 緩衝區初始化置空
將檔案內容讀入緩衝區
使用send將緩衝區內容傳送到伺服器
檔案內容傳送完成
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 8888 /*偵聽埠地址*/ int main(int argc, char *argv[]) { int s; /*s為socket描述符*/ struct sockaddr_in server_addr; /*伺服器地址結構*/ s = socket(AF_INET, SOCK_STREAM, 0); /*建立一個流式套接字 */ if(s < 0){ /*出錯*/ printf("socket error\n"); return -1; } /*設定伺服器地址*/ bzero(&server_addr, sizeof(server_addr)); /*清零*/ server_addr.sin_family = AF_INET; /*協議族*/ server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*本地地址*/ server_addr.sin_port = htons(PORT); /*伺服器埠*/ /*將使用者輸入的字串型別的IP地址轉為整型*/ inet_pton(AF_INET, argv[1], &server_addr.sin_addr); /*連線伺服器*/ connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr)); process_conn_client(s); /*客戶端處理過程*/ close(s); /*關閉連線*/ return 0; }
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 1024
/*客戶端的處理過程*/
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[BUFFER_SIZE];
FILE *stream;
int length=0;
char buffer_add[BUFFER_SIZE]={'\0'};
for(;;){
size = read(s, buffer, BUFFER_SIZE-length);
if(size <= 0){
return;
}
strcat(buffer_add, buffer);
length+=size;
if(length>=BUFFER_SIZE) break;
}
printf("%s", buffer_add);
scanf("%s", buffer);
write(s, buffer, BUFFER_SIZE);
if((stream=fopen(buffer, "r"))==NULL) return;
printf("ing...\n");
for(;;){
size = fread(buffer, sizeof(char), BUFFER_SIZE, stream);
if(size <= 0){
return;
}
write(s, buffer, size);
}
fclose(stream);
}