當客戶端連接上服務器后,服務器會將相應文件傳輸給客戶端,實現文件下載。
思路服務器端,主進程負責listen。循環內,主進程每從任務請求隊列中accept出一個請求,就fork出孫子完成文件傳輸。注意:如果只是fork出兒子,那么主進程就得wait兒子,這樣的話,只有當給一個客戶端傳完文件后才能下一個。
代碼server端
/************************************************************************* > File Name: server.c > Author: KrisChou > Mail:zhoujx0219@163.com > Created Time: Thu 28 Aug 2014 09:40:32 PM CST ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <netdb.h>#define SNDSIZE 1024*1024 //1M,注意如果棧空間(可以設置的)沒這么大,就用堆空間#define FILE_NAME "a.rmvb"int main(int argc,char* argv[])// exe config{ /* 從配置文件中讀取服務器聯系方式:ip以及端口號 */ int fd_conf ; fd_conf = open(argv[1], O_RDONLY) ; FILE* fp_conf = fdopen(fd_conf, "r"); //秀一下fdopen函數,文件描述符轉換為文件指針 fdopen(int fd, const char *mode) char my_ip[32]=""; int my_port ; fscanf(fp_conf, "%s%d", my_ip, &my_port); close(fd_conf); fclose(fp_conf); /* 創建服務器的監聽socket端口 */ int fd_listen fd_listen = socket(AF_INET, SOCK_STREAM, 0); if(fd_listen == -1) { perror("socket"); } /* 為服務器socket端口綁定聯系方式,以便讓客戶端connect */ struct sockaddr_in server_addr ; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET ; server_addr.sin_port = htons(my_port); server_addr.sin_addr.s_addr = inet_addr(my_ip); if(-1 == bind(fd_listen, (struct sockaddr *)&server_addr, sizeof(server_addr)) ) { perror("bind"); close(fd_listen); exit(1); } /* listen */ if(-1 == listen(fd_listen, 5)) { perror("listen"); close(fd_listen); exit(1); } /* accept */ int fd_client; /* 客戶端socket端口的另一頭 */ struct sockaddr_in client_addr ; /* 客戶端聯系方式,以accept函數的傳出參數給出 */ int len ; memset(&client_addr, 0, sizeof(client_addr)); len = sizeof(client_addr); while(1) { fd_client = accept(fd_listen, (struct sockaddr *)&client_addr, &len); if(fd_client == -1) { continue ; } PRintf("a client connect ! ip:port %s:%d/n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port)); if(fork() == 0) { close(fd_listen); //對于子進程和孫子進程都不需要listen端口,直接關閉。 if(fork() == 0) { int fd_file = open(FILE_NAME, O_RDONLY); //打開客戶端要下載的文件 char buf[SNDSIZE] ; int snd_cnt = 0 ; int readn ; /* 從文件中讀取數據,并發送給客戶端 */ while(memset(buf, 0,SNDSIZE ), (readn = read(fd_file,buf, SNDSIZE)) > 0) { if(send(fd_client, buf, readn, 0) != readn) { printf("send error! /n"); } snd_cnt ++ ; } printf("send over: %d /n", snd_cnt); close(fd_file); close(fd_client); exit(0); } close(fd_client); exit(0); } close(fd_client); wait(NULL) ; } return 0 ;}client端
/************************************************************************* > File Name: client.c > Author: KrisChou > Mail:zhoujx0219@163.com > Created Time: Thu 28 Aug 2014 11:59:20 PM CST ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <netdb.h>#define SNDSIZE 1024*1024#define SERVER_PORT 6080 // 服務器端口int main(int argc, char *argv[]) EXE IP{ /* socket */ int fd_client; fd_client = socket(AF_INET, SOCK_STREAM, 0); if(fd_client == -1) { perror("socket"); exit(1); } /* 存放所連服務器信息的結構體 */ struct sockaddr_in server_addr; memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); server_addr.sin_addr.s_addr = inet_addr(argv[1]); /* connect */ while(connect(fd_client, (struct sockaddr *)&server_addr,sizeof(server_addr)) == -1) { /* 當connect返回-1時,說明服務器還沒有啟動 */ sleep(1); printf("connecting... /n"); } printf("connect success! /n"); int fd_write = open("txt", O_WRONLY | O_CREAT);//下載的內容寫入本地文件中 char buf[SNDSIZE]; int readn; int recv_cnt = 0; while(memset(buf,0,SNDSIZE),(readn = recv(fd_client,buf,SNDSIZE,0)) > 0) { write(fd_write,buf,readn); recv_cnt++; } printf("recv over: %d /n", recv_cnt); close(fd_write); close(fd_client); return 0;}新聞熱點
疑難解答