总体需求:
编写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.服务器端参考代码

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. #include<unistd.h>
  5. #include<sys/types.h>
  6. #include<sys/socket.h>
  7. #include<netinet/in.h>
  8. #include<arpa/inet.h>
  9. #include<fcntl.h>
  10. #include<dirent.h>
  11. #include<errno.h>
  12. #define N 128
  13. #define PORT_NUM 8888
  14. typedef struct sockaddr SA;
  15. void ProcessList(int connfd)
  16. {
  17. char buf[N];
  18. DIR *mydir;
  19. struct dirent *myitem;
  20. mydir = opendir(".");
  21. while((myitem = readdir(mydir)) != NULL){
  22. if((strcmp(myitem->d_name, ".") == 0) || (strcmp(myitem->d_name, "..") == 0))
  23. continue;
  24. strcpy(buf, myitem->d_name);
  25. send( connfd, buf, N, 0);
  26. }
  27. close(connfd);
  28. return;
  29. }
  30. void ProcessGet(int connfd, char buf[])
  31. {
  32. int fd,nbyte;
  33. if(( fd = open(buf+1, O_RDONLY)) < 0){
  34. fprintf(stderr, "fail to open %s: %s\n",buf+1,strerror(errno));
  35. buf[0] = 'N';
  36. send(connfd, buf, N, 0);
  37. return;
  38. }
  39. buf[0] = 'Y';
  40. send(connfd, buf, N, 0);
  41. while(( nbyte = read( fd, buf, N)) > 0){
  42. send(connfd, buf, nbyte, 0);
  43. }
  44. close(connfd);
  45. return;
  46. }
  47. void ProcessPut(int connfd, char buf[])
  48. {
  49. int fd, nbyte;
  50. if(( fd = open(buf+1, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0){
  51. printf("fail to create %s on server\n",buf+1);
  52. return;
  53. }
  54. while(( nbyte = recv( connfd, buf, N, 0)) > 0){
  55. write(fd, buf, nbyte);
  56. }
  57. close(fd);
  58. return;
  59. }
  60. int main(int argc, char *argv[])
  61. {
  62. int listenfd, connfd;
  63. int optval = 1;
  64. char buf[N];
  65. struct sockaddr_in server_addr;
  66. if(( listenfd = socket( AF_INET, SOCK_STREAM, 0)) < 0 ){
  67. fprintf(stderr, "fail to socket: %s\n",strerror(errno));
  68. exit(-1);
  69. }
  70. #ifdef _DEBUG_
  71. printf("socket is %d\n", listenfd);
  72. #endif
  73. memset(&server_addr, 0, sizeof(server_addr));
  74. server_addr.sin_family = AF_INET;
  75. server_addr.sin_port = htons(PORT_NUM);
  76. server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  77. setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
  78. if( bind( listenfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
  79. perror("fail to bind");
  80. exit(-1);
  81. }
  82. listen( listenfd, 5);
  83. while(1){
  84. if(( connfd = accept(listenfd, NULL, NULL)) < 0){
  85. perror("fail to accept");
  86. break;
  87. }
  88. recv( connfd, buf, N, 0);
  89. switch(buf[0]){
  90. case 'L': ProcessList(connfd);
  91. break;
  92. case 'G': ProcessGet(connfd, buf);
  93. break;
  94. case 'P': ProcessPut(connfd, buf);
  95. break;
  96. default: printf("Input ");
  97. }
  98. close(connfd);
  99. }
  100. return 0;
  101. }

2.客户端参考代码:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<unistd.h>
  4. #include<string.h>
  5. #include<fcntl.h>
  6. #include<errno.h>
  7. #include<sys/types.h>
  8. #include<sys/socket.h>
  9. #include<netinet/in.h>
  10. #include<arpa/inet.h>
  11. #define N 128
  12. #define PORT_NUM 8888
  13. typedef struct sockaddr SA;
  14. void PrintHelp()
  15. {
  16. printf("help: display help info\n");
  17. printf("list: get file list of server\n");
  18. printf("get : get <file>\n");
  19. printf("put : put <file>\n");
  20. printf("quit: quit the client\n");
  21. return;
  22. }
  23. void ProcessList(struct sockaddr_in server_addr)
  24. {
  25. int sockfd, nbyte;
  26. char buf[N];
  27. if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
  28. printf("fail to list\n");
  29. return;
  30. }
  31. if( connect(sockfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
  32. printf("fail to connect server\n");
  33. goto ERROR_1;
  34. }
  35. strcpy(buf, "L");
  36. send(sockfd, buf, N, 0);
  37. while(( nbyte = recv( sockfd, buf, N, 0)) != 0){
  38. printf("%s\n",buf);
  39. }
  40. ERROR_1:
  41. close(sockfd);
  42. return;
  43. }
  44. void ProcessGet(struct sockaddr_in server_addr, char command[])
  45. {
  46. int sockfd, nbyte, fd;
  47. char buf[N];
  48. if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
  49. printf("fail to get\n");
  50. return;
  51. }
  52. if( connect( sockfd, (SA *)(&server_addr), sizeof(server_addr)) < 0){
  53. printf("fail to connect server\n");
  54. goto ERROR_2;
  55. }
  56. sprintf(buf, "G%s", command+4);
  57. send(sockfd, buf, N, 0);
  58. recv(sockfd, buf, N, 0);
  59. if(buf[0] == 'N'){
  60. printf("No such file on server\n");
  61. goto ERROR_2;
  62. }
  63. if(( fd = open(command+4, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0){
  64. printf("fail to create local file %s\n",command+4);
  65. goto ERROR_2;
  66. }
  67. while(( nbyte = recv(sockfd, buf, N, 0)) > 0){
  68. write(fd, buf, nbyte);
  69. }
  70. close(fd);
  71. ERROR_2:
  72. close(sockfd);
  73. return;
  74. }
  75. void ProcessPut(struct sockaddr_in server_addr, char command[])
  76. {
  77. int sockfd, fd, nbyte;
  78. char buf[N];
  79. if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
  80. printf("fail to get\n");
  81. return;
  82. }
  83. if( connect(sockfd,(SA *)(&server_addr),sizeof(server_addr)) < 0){
  84. printf("fail to connect server\n");
  85. goto ERROR_3;
  86. }
  87. if((fd = open(command+4, O_RDONLY)) < 0){
  88. printf("fail to open %s\n",command+4);
  89. goto ERROR_3;
  90. }
  91. sprintf(buf, "P%s", command+4);
  92. send(sockfd, buf, N, 0);
  93. while(( nbyte = read(fd, buf, N)) > 0){
  94. send(sockfd, buf, nbyte, 0);
  95. }
  96. close(fd);
  97. ERROR_3:
  98. close(sockfd);
  99. return;
  100. }
  101. int main(int argc, char *argv[])
  102. {
  103. int sockfd, fd, nbyte;
  104. char command[32];
  105. struct sockaddr_in server_addr;
  106. if(argc < 3){
  107. printf("Usage: %s <server_ip> <port>\n",argv[0]);
  108. exit(-1);
  109. }
  110. if(( sockfd = socket( AF_INET, SOCK_STREAM, 0)) < 0){
  111. fprintf(stderr, "fail to socket: %s\n", strerror(errno));
  112. exit(-1);
  113. }
  114. #ifdef _DEBUG_
  115. printf("socket is %d\n",sockfd);
  116. #endif
  117. memset(&server_addr, 0, sizeof(server_addr));
  118. server_addr.sin_family = AF_INET;
  119. server_addr.sin_port = htons(atoi(argv[2]));
  120. server_addr.sin_addr.s_addr = inet_addr(argv[1]);
  121. //server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  122. while(1){
  123. printf("<client>");
  124. fgets(command, 32, stdin);
  125. command[strlen(command)-1] = '\0';
  126. if(strcmp( command, "help") == 0){
  127. PrintHelp();
  128. }
  129. else if(strcmp( command, "list") == 0){
  130. ProcessList(server_addr);
  131. }
  132. else if(strncmp( command, "get", 3) == 0){
  133. ProcessGet(server_addr, command);
  134. }
  135. else if(strncmp( command, "put", 3) == 0){
  136. ProcessPut(server_addr, command);
  137. }
  138. else if(strcmp( command, "quit") == 0){
  139. printf("Bye\n");
  140. break;
  141. }
  142. else{
  143. printf("Wrong command, 'help' for command list.\n");
  144. }
  145. }
  146. return 0;
  147. }

3.验证结果(ubuntu14.04)

Linux c实现一个tcp文件服务器和客户端的更多相关文章

  1. linux epoll机制对TCP 客户端和服务端的监听C代码通用框架实现

    1 TCP简介 tcp是一种基于流的应用层协议,其“可靠的数据传输”实现的原理就是,“拥塞控制”的滑动窗口机制,该机制包含的算法主要有“慢启动”,“拥塞避免”,“快速重传”. 2 TCP socket ...

  2. Linux系统编程(32)—— socket编程之TCP服务器与客户端

    TCP协议的客户端/服务器程序的一般流程 服务器调用socket().bind().listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后, ...

  3. 利用socket编程在ESP32上搭建一个TCP客户端

    通过之前http://www.cnblogs.com/noticeable/p/7636582.html中对socket的编程,已经可以知道如何通过socket编程搭建服务器和客户端了,现在,就在ES ...

  4. 在Linux系统下搭建和配置一个minio文件服务器(二)

    上一篇主要讲述了在linux系统中搭建一个minio文件服务器,那么这一篇则用来整合java代码中使用,我之前自己已经搭建好了一个springboot项目,那么这一篇将详细讲述如何把minio整合进s ...

  5. 网络编程—【自己动手】用C语言写一个基于服务器和客户端(TCP)!

    如果想要自己写一个服务器和客户端,我们需要掌握一定的网络编程技术,个人认为,网络编程中最关键的就是这个东西--socket(套接字). socket(套接字):简单来讲,socket就是用于描述IP地 ...

  6. 在 Linux 上配置一个 syslog 服务器

    syslog服务器可以用作一个网络中的日志监控中心,所有能够通过网络来发送日志的设施(包含了Linux或Windows服务器,路由器,交换机以及其他主机)都可以把日志发送给它. 通过设置一个syslo ...

  7. Linux 系统安全 抵御TCP的洪水

    抵御TCP的洪水 分类: LINUX tcp_syn_retries :INTEGER默认值是5对 于一个新建连接,内核要发送多少个 SYN 连接请求才决定放弃.不应该大于255,默认值是5,对应于1 ...

  8. Linux内核中影响tcp三次握手的一些协议配置

    在Linux的发行版本中,都存在一个/proc/目录,有的也称它为Proc文件系统.在 /proc 虚拟文件系统中存在一些可调节的内核参数.这个文件系统中的每个文件都表示一个或多个参数,它们可以通过 ...

  9. linux下socket编程-TCP

    网络字节序 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出,接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存,因此,网络数据流的地址应这样规定:先发出 ...

随机推荐

  1. CSS的 背景属性

    ㈠背景色  background-color ⑴background-color 属性设置元素的背景颜色. ⑵元素背景的范围: background-color 属性为元素设置一种纯色.这种颜色会填充 ...

  2. 在linux 下安装git

    ① 安装 Git Linux 做为服务器端系统,Windows 作为客户端系统,分别安装 Git 服务器端: #yum install -y git 安装完后,查看 Git 版本 [root@loca ...

  3. [shell]管道连接的命令判断返回值

    场景: 在bash执行管道连接的命令,需要获取到各个命令的返回值用于判断 在脚本中我们可能需要将执行结果打印到屏幕,同时保存在文件中供后面分析用,写出如下的命令 command 2>&1 ...

  4. axios多并发请求

    场景: 点击导出Excel按钮实现,姓名列表中前五个的所有的文章数据发送给后端,姓名列表中点击过的数据会被存放到localStorage中: 思路: 点击导出按钮,把前五个数据逐个和localStor ...

  5. input选择框默认样式修改

    input选择框是无法直接修改样式,我们只能间接来改变它样式. 原理:用图片来代替原来的input选择框,原来的input选择框定位到图片上方并让它opacity为0,鼠标点击时用js来改变图片,这样 ...

  6. python下selenium模拟浏览器基础操作

    1.安装及下载 selenium安装: pip install selenium  即可自动安装selenium geckodriver下载:https://github.com/mozilla/ge ...

  7. 在浏览器访问Tomcat的时候报错java.lang.IllegalArgumentException: Control character in cookie value or attribute.

    出现这种情况的原因就是因为cookie中存在中文或者特殊符号造成的,应为Tomcat7不支持 解决方法: 1,首先必须先删除本地的cookie,否则项目无法访问 2,然后调整编码就行了

  8. C++入门经典-例5.17-右值引用的定义

    1:右值引用的定义: 类型 && i=被引用的对象: 左值与右值的区别在于,右值是临时变量,例如,函数的返回值,并且无法被改变. 当右值引用被初始化后,临时变量消失. 代码如下: // ...

  9. python3笔记十三:python数据类型-Set集合

    一:学习内容 集合概念 集合创建 集合添加 集合插入 集合删除 集合访问 集合操作:并集.交集 二:集合概念 1.set:类似dict,是一组key的集合,不存储value 2.本质:无序和无重复元素 ...

  10. 1.zookeeper原理解析-数据存储之Zookeeper内存结构

    Zookeeper是怎么存储数据的,什么机制保证集群中数据是一致性,在网络异常,当机以及停电等异常情况下恢复数据的,我们知道数据库给我们提供了这些功能,其实zookeeper也实现了类似数据库的功能. ...