需求

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

思路

服务器端,主进程负责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;
}

最新文章

  1. ABP源码分析二:ABP中配置的注册和初始化
  2. python中的TypeError错误解决办法
  3. css负边距之详解
  4. SQL Server性能调优系列
  5. phongap、APICloud、ionic等app开发平台你都知道吗?
  6. OpenCV Template Matching Subpixel Accuracy
  7. kprobe原理解析(二)
  8. 关于java中JButton的样式设置(的一些我们应该知道的函数)(转)
  9. iOS 细节 问题
  10. css中关于transform、transition、animate的区别
  11. 深入学习Java中的字符串,代码点和代码单元
  12. linux下Nginx配置文件(nginx.conf)配置设置详解(windows用phpstudy集成)
  13. 对Spring运用的一些思考
  14. Confluence 6 workbox 配置查询间隔
  15. mysql数据库优化(四)-项目实战
  16. Linux结构目录
  17. 《mysql从入门到精通》提高
  18. Codeforces.GYM101612E.Equal Numbers(贪心)
  19. Underscore.js部分讲解
  20. 【转】 .Net MVC4 上传大文件,并保存表单

热门文章

  1. Android保存图片到系统图库
  2. linux eclipse
  3. Eclipse基金会
  4. MongoDB 数据类型
  5. Charles移动端抓包工具使用
  6. MVC 初始 Log4net (一)
  7. verilog 奇数分频设计
  8. 闪回flashback
  9. xml基础学习笔记03
  10. 【Binary Tree Preorder Traversal】cpp