Linux网络编程6——使用TCP实现文件服务器
需求
当客户端连接上服务器后,服务器会将相应文件传输给客户端,实现文件下载。
思路
服务器端,主进程负责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;
}
Linux网络编程6——使用TCP实现文件服务器的更多相关文章
- Linux网络编程:基于TCP的程序开发回顾篇《转》
面向连接的TCP程序设计 基于TCP的程序开发分为服务器端和客户端两部分,常见的核心步骤和流程: 其实按照上面这个流程调用系统API确实可以完全实现应用层程序的开发,一点问题没有.可随着时间的推移,你 ...
- 【深入浅出Linux网络编程】 “实践 -- TCP & UDP”
通过上一篇博客的学习,你应该对基于epoll的事件触发机制有所掌握,并且通过阅读sio.c/sio.h应该也学会了如何封装epoll以及如何通过设计令epoll更加实用(用户回调,用户参数). 简单回 ...
- Linux网络编程--wireshark分析TCP包头的格式
摘要: 本文简介了TCP面向连接理论知识,具体讲述了TCP报文各个字段含义.并从Wireshark俘获分组中选取TCP连接建立相关报文段进行分析. 一.概述 TCP是面向连接的可靠传输 ...
- Linux网络编程——浅谈 TCP 三次握手和四次挥手
一.tcp协议格式 二.三次握手 在 TCP/IP 协议中.TCP 协议提供可靠的连接服务,採用三次握手建立一个连接. 第一次握手:建立连接时,client发送 syn 包(tcp协议中syn位置1. ...
- Linux网络编程二、tcp连接API
一.服务端 1.创建套接字: int socket(int domain, int type, int protocol); domain:指定协议族,通常选用AF_INET. type:指定sock ...
- Linux网络编程9——对TCP与UDP的简易封装2.0
具体生成动态库的操作及使用该动态库的操作请参见上篇博文.以下仅仅列出改进版本的代码. 代码 my_socket.h #ifndef __MY_SOCKET_H__ #define __MY_SOCKE ...
- Linux网络编程8——对TCP与UDP的简易封装
引言 每次使用socket通信,都会有很对相似的操作.本文,会对TCP与UDP通信做一简单封装,并生成动态库. 代码 my_socket.h #ifndef __MY_SOCKET_H__ #defi ...
- 【Linux 网络编程】常用TCP/IP网络编程函数
(1)函数socket /**************************************************************** ** 功能:创建一个套接字用于通信 ** 参 ...
- Linux网络编程7——使用TCP实现双方聊天
思路 主线程负责发送消息,另一线程负责接收消息.服务端和客户端均是如此. 注意 当A方close掉用于通信的socket端口后,该端口是不会立即关闭的.因为此时可能B方的信息还没send完.因此,此时 ...
随机推荐
- Labview实现脉波调制( PDM )
Labview实现脉波调制( PDM ) 根据定义为脉冲宽度调制 生成一个正弦信号,得到其幅值输入给一个方波信号的占空比 由于方波信号的占空比里面含有正弦信号的信息 因此通过滤出方波信号的占空比信息则 ...
- 网页设计师必备的10个CSS技巧
CSS是网页设计师的基础,对CSS的了解能使他们能够设计出更加美观别致的网页.使用CSS技巧来巧妙地处理CSS是非常令设计师着迷的事情.在CSS的深海世界里有很多有意思的东西,你只需要找到最适合你的就 ...
- 关于spring mvc MaxUploadSizeExceededException 死循环解决方案
当看到这文章的时候相信你现在应该遇到这样的问题了,我也是自己遇到了后来找到解决方案了记录下来,如果下次遇到就可以直接解决了. 至于为什么会出现这样的情况,可以看这篇文章:https://bz.apac ...
- mozilla css developer center
https://developer.mozilla.org/en-US/docs/Web/CSS
- 20145120 《Java程序设计》实验三实验报告
20145120 <Java程序设计>实验三实验报告 实验名称:敏捷开发与XP实践 实验目的与要求: XP基础 XP核心实践 相关工具 (一)敏捷开发与XP 极限编程(eXtreme Pr ...
- 向Array中添加插入排序
插入排序思路 从第二个元素开始和它前面的元素进行比较,如果比前面的元素小,那么前面的元素向后移动,否则就将此元素插入到相应的位置. 插入排序实现 Function.prototype.method = ...
- springmvc返回jsp源代码解决办法
url-pattern问题 spring用到forward("/WEB-INF/jsp/*.jsp")而forward当然是又要经过web.xml的映射的,然后,在URL匹配时, ...
- 【 Regular Expression Matching 】cpp
题目: Implement regular expression matching with support for '.' and '*'. '.' Matches any single chara ...
- throttle/debounce: 为你的cpu减减压(前端性能优化)
何为throttle, 何为debounce? 谷歌翻译给出的意思:throttle 掐死??? debounce 去抖 好吧,按理解我们习惯翻译成 ——节流. 那么在什么场景下需要用到? 场景一 ...
- Gulp的安装
Gulp 是前端自动化开发工具,我们可以用它提高开发效率. 它有以下用途: 压缩js.压缩css.压缩less.压缩图片等功能 首先我们开始安装Gulp Gulp是基于node来实现的,所以应该先安装 ...