Linux c实现一个tcp文件服务器和客户端
总体需求:
编写tcp文件服务器和客户端。客户端可以上传和下载文件。
================================================
分解需求
客户端功能描述:
1)要求支持以下命令:
help: 显示客户端所有命令和说明, 在本地实现即可,help的内容不需要从服务器传回。
list: 显示服务器端可下载文件列表,列表内容需要从服务器端传回。
get <filename>: 根据<filename>下载指定文件,<filename>只包含文件名,如果出现"/"等字符任务是路径,不予支持;下载后的文件存放在当前工作路径下即可。
put <pathname>: 上传文件 <pathname> 必须为客户端本机的合法路径,客户端搜索到文件后推送给服务器
quit: 退出客户端
2)客户端启动后可以反复输入命令,除非用户输入quit才会退出。
3) 每次命令(list/get/put)建立一个连接,命令执行完毕后关闭该连接。
服务器端功能:
1)文件服务器不要求支持并发,同时只支持一个连接,即一个客户端发起的一次命令。一次命令执行完毕后关闭连接并继续等待下一次连接请求。
2)文件服务器启动后一直执行,除非被人为强制关闭。
3)文件服务器端需要设定一个目录用于存放所有的文件,该目录路径不支持可配置,且该目录不要求再包含子目录。称其为"文件存放目录"。
4)对list服务,服务器端从"文件存放目录"下列举出所有的文件名称并发送给客户端。
5)对get服务,服务器根据用户指定的文件名缺省从"文件存放目录"搜索该文件并推送文件到客户端,推送不会删除原服务器上的文件。
6)对put服务,服务器将用户推送的文件存储到"文件存放目录",如果存在同名的文件则拒绝。
7)若执行命令和传输过程中发生错误,关闭当前连接并进入等待下一个连接。
=================================================
提示:
请在编码前仔细设计一个简单的应用层协议规定客户端和服务器端之间命令传输的请求和应答流程和格式。
二。参考代码:
1.服务器端参考代码
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #include<arpa/inet.h>
- #include<fcntl.h>
- #include<dirent.h>
- #include<errno.h>
- #define N 128
- #define PORT_NUM 8888
- typedef struct sockaddr SA;
- void ProcessList(int connfd)
- {
- char buf[N];
- DIR *mydir;
- struct dirent *myitem;
- mydir = opendir(".");
- while((myitem = readdir(mydir)) != NULL){
- if((strcmp(myitem->d_name, ".") == 0) || (strcmp(myitem->d_name, "..") == 0))
- continue;
- strcpy(buf, myitem->d_name);
- send( connfd, buf, N, 0);
- }
- close(connfd);
- return;
- }
- void ProcessGet(int connfd, char buf[])
- {
- int fd,nbyte;
- if(( fd = open(buf+1, O_RDONLY)) < 0){
- fprintf(stderr, "fail to open %s: %s\n",buf+1,strerror(errno));
- buf[0] = 'N';
- send(connfd, buf, N, 0);
- return;
- }
- buf[0] = 'Y';
- send(connfd, buf, N, 0);
- while(( nbyte = read( fd, buf, N)) > 0){
- send(connfd, buf, nbyte, 0);
- }
- close(connfd);
- return;
- }
- void ProcessPut(int connfd, char buf[])
- {
- int fd, nbyte;
- if(( fd = open(buf+1, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0){
- printf("fail to create %s on server\n",buf+1);
- return;
- }
- while(( nbyte = recv( connfd, buf, N, 0)) > 0){
- write(fd, buf, nbyte);
- }
- close(fd);
- return;
- }
- int main(int argc, char *argv[])
- {
- int listenfd, connfd;
- int optval = 1;
- char buf[N];
- struct sockaddr_in server_addr;
- if(( listenfd = socket( AF_INET, SOCK_STREAM, 0)) < 0 ){
- fprintf(stderr, "fail to socket: %s\n",strerror(errno));
- exit(-1);
- }
- #ifdef _DEBUG_
- printf("socket is %d\n", listenfd);
- #endif
- memset(&server_addr, 0, sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(PORT_NUM);
- server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
- if( bind( listenfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
- perror("fail to bind");
- exit(-1);
- }
- listen( listenfd, 5);
- while(1){
- if(( connfd = accept(listenfd, NULL, NULL)) < 0){
- perror("fail to accept");
- break;
- }
- recv( connfd, buf, N, 0);
- switch(buf[0]){
- case 'L': ProcessList(connfd);
- break;
- case 'G': ProcessGet(connfd, buf);
- break;
- case 'P': ProcessPut(connfd, buf);
- break;
- default: printf("Input ");
- }
- close(connfd);
- }
- return 0;
- }
2.客户端参考代码:
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<string.h>
- #include<fcntl.h>
- #include<errno.h>
- #include<sys/types.h>
- #include<sys/socket.h>
- #include<netinet/in.h>
- #include<arpa/inet.h>
- #define N 128
- #define PORT_NUM 8888
- typedef struct sockaddr SA;
- void PrintHelp()
- {
- printf("help: display help info\n");
- printf("list: get file list of server\n");
- printf("get : get <file>\n");
- printf("put : put <file>\n");
- printf("quit: quit the client\n");
- return;
- }
- void ProcessList(struct sockaddr_in server_addr)
- {
- int sockfd, nbyte;
- char buf[N];
- if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
- printf("fail to list\n");
- return;
- }
- if( connect(sockfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
- printf("fail to connect server\n");
- goto ERROR_1;
- }
- strcpy(buf, "L");
- send(sockfd, buf, N, 0);
- while(( nbyte = recv( sockfd, buf, N, 0)) != 0){
- printf("%s\n",buf);
- }
- ERROR_1:
- close(sockfd);
- return;
- }
- void ProcessGet(struct sockaddr_in server_addr, char command[])
- {
- int sockfd, nbyte, fd;
- char buf[N];
- if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
- printf("fail to get\n");
- return;
- }
- if( connect( sockfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
- printf("fail to connect server\n");
- goto ERROR_2;
- }
- sprintf(buf, "G%s", command+4);
- send(sockfd, buf, N, 0);
- recv(sockfd, buf, N, 0);
- if(buf[0] == 'N'){
- printf("No such file on server\n");
- goto ERROR_2;
- }
- if(( fd = open(command+4, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0){
- printf("fail to create local file %s\n",command+4);
- goto ERROR_2;
- }
- while(( nbyte = recv(sockfd, buf, N, 0)) > 0){
- write(fd, buf, nbyte);
- }
- close(fd);
- ERROR_2:
- close(sockfd);
- return;
- }
- void ProcessPut(struct sockaddr_in server_addr, char command[])
- {
- int sockfd, fd, nbyte;
- char buf[N];
- if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
- printf("fail to get\n");
- return;
- }
- if( connect(sockfd,(SA *)(&server_addr),sizeof(server_addr)) < 0){
- printf("fail to connect server\n");
- goto ERROR_3;
- }
- if((fd = open(command+4, O_RDONLY)) < 0){
- printf("fail to open %s\n",command+4);
- goto ERROR_3;
- }
- sprintf(buf, "P%s", command+4);
- send(sockfd, buf, N, 0);
- while(( nbyte = read(fd, buf, N)) > 0){
- send(sockfd, buf, nbyte, 0);
- }
- close(fd);
- ERROR_3:
- close(sockfd);
- return;
- }
- int main(int argc, char *argv[])
- {
- int sockfd, fd, nbyte;
- char command[32];
- struct sockaddr_in server_addr;
- if(argc < 3){
- printf("Usage: %s <server_ip> <port>\n",argv[0]);
- exit(-1);
- }
- if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
- fprintf(stderr, "fail to socket: %s\n", strerror(errno));
- exit(-1);
- }
- #ifdef _DEBUG_
- printf("socket is %d\n",sockfd);
- #endif
- memset(&server_addr, 0, sizeof(server_addr));
- server_addr.sin_family = AF_INET;
- server_addr.sin_port = htons(atoi(argv[2]));
- server_addr.sin_addr.s_addr = inet_addr(argv[1]);
- //server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- while(1){
- printf("<client>");
- fgets(command, 32, stdin);
- command[strlen(command)-1] = '\0';
- if(strcmp( command, "help") == 0){
- PrintHelp();
- }
- else if(strcmp( command, "list") == 0){
- ProcessList(server_addr);
- }
- else if(strncmp( command, "get", 3) == 0){
- ProcessGet(server_addr, command);
- }
- else if(strncmp( command, "put", 3) == 0){
- ProcessPut(server_addr, command);
- }
- else if(strcmp( command, "quit") == 0){
- printf("Bye\n");
- break;
- }
- else{
- printf("Wrong command, 'help' for command list.\n");
- }
- }
- return 0;
- }

3.验证结果(ubuntu14.04)
Linux c实现一个tcp文件服务器和客户端的更多相关文章
- linux epoll机制对TCP 客户端和服务端的监听C代码通用框架实现
1 TCP简介 tcp是一种基于流的应用层协议,其“可靠的数据传输”实现的原理就是,“拥塞控制”的滑动窗口机制,该机制包含的算法主要有“慢启动”,“拥塞避免”,“快速重传”. 2 TCP socket ...
- Linux系统编程(32)—— socket编程之TCP服务器与客户端
TCP协议的客户端/服务器程序的一般流程 服务器调用socket().bind().listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后, ...
- 利用socket编程在ESP32上搭建一个TCP客户端
通过之前http://www.cnblogs.com/noticeable/p/7636582.html中对socket的编程,已经可以知道如何通过socket编程搭建服务器和客户端了,现在,就在ES ...
- 在Linux系统下搭建和配置一个minio文件服务器(二)
上一篇主要讲述了在linux系统中搭建一个minio文件服务器,那么这一篇则用来整合java代码中使用,我之前自己已经搭建好了一个springboot项目,那么这一篇将详细讲述如何把minio整合进s ...
- 网络编程—【自己动手】用C语言写一个基于服务器和客户端(TCP)!
如果想要自己写一个服务器和客户端,我们需要掌握一定的网络编程技术,个人认为,网络编程中最关键的就是这个东西--socket(套接字). socket(套接字):简单来讲,socket就是用于描述IP地 ...
- 在 Linux 上配置一个 syslog 服务器
syslog服务器可以用作一个网络中的日志监控中心,所有能够通过网络来发送日志的设施(包含了Linux或Windows服务器,路由器,交换机以及其他主机)都可以把日志发送给它. 通过设置一个syslo ...
- Linux 系统安全 抵御TCP的洪水
抵御TCP的洪水 分类: LINUX tcp_syn_retries :INTEGER默认值是5对 于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃.不应该大于255,默认值是5,对应于1 ...
- Linux内核中影响tcp三次握手的一些协议配置
在Linux的发行版本中,都存在一个/proc/目录,有的也称它为Proc文件系统.在 /proc 虚拟文件系统中存在一些可调节的内核参数.这个文件系统中的每个文件都表示一个或多个参数,它们可以通过 ...
- linux下socket编程-TCP
网络字节序 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存,因此,网络数据流的地址应这样规定:先发出 ...
随机推荐
- Win10 搭建IIS服务
IIS服务器,俗称:Web服务器又或者叫做网站服务器. IIS详解: https://baike.baidu.com/item/iis/99720?fr=aladdin 开始搭建: 1. 打开控制面板 ...
- Java多线程和并发(二),Thread中的start和run的区别
目录 1.调用run方法 2.调用start方法 3.start和run的区别 二.Thread中的start和run的区别 1.调用run方法 public class ThreadTest { p ...
- ueditor+复制word+图片不能上传
最近公司做项目需要实现一个功能,在网页富文本编辑器中实现粘贴Word图文的功能. 我们在网站中使用的Web编辑器比较多,都是根据用户需求来选择的.目前还没有固定哪一个编辑器 有时候用的是UEditor ...
- luoguP3203 [HNOI2010]BOUNCE 弹飞绵羊
P3203 [HNOI2010]BOUNCE 弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonke ...
- C语言写数据库(一)
/*** connect.c ***/ #include<stdio.h> #include<stdlib.h> #include"mysql.h" int ...
- java取小数点后两位
package com.yonyou.sud.algorithm; import java.math.BigDecimal;import java.text.DecimalFormat;/*** ja ...
- Hibernate理解?
(1)Hibernate是对象关系映射框架,对JDBC进行非常轻量级的对象封装,是全自动的ORM框架,可以自动生成SQL语句.自动执行. (2)语言特点 <1>将对数据库的操作转换为对Ja ...
- winscp连接后目录名称乱码
1.点击[编辑](点后变为保存按钮)按钮,高级按钮变为可用,点击[高级] 2.文件名utf-8编码,默认为“自动”,勾选为“开启”
- C++入门经典-例5.14-丢失的内存,关于内存泄漏
1:代码如下: // 5.14.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> usin ...
- spark 笔记 6: RDD
了解RDD之前,必读UCB的论文,个人认为这是最好的资料,没有之一. http://www.cs.berkeley.edu/~matei/papers/2012/nsdi_spark.pdf A Re ...