您的位置:首页 > 理论基础 > 计算机网络

Linux网络编程6——使用TCP实现文件服务器

2016-07-29 00:00 239 查看

需求

当客户端连接上服务器后,服务器会将相应文件传输给客户端,实现文件下载。

思路

服务器端,主进程负责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; }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: