http://blog.csdn.net/qq_25425023/article/details/53914820

回射服务器就是服务端将客户端的数据发送回去。

我实现的回射服务器返回增加了时间。

服务端代码,可以很容易看懂:

[cpp] view plain copy
  1. #include <sys/socket.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <netinet/in.h>
  6. #include <time.h>
  7. #include <unistd.h>
  8. #include <arpa/inet.h>
  9. #include <stdlib.h>
  10. #include "../thread_pool.h"  //在上一篇博客中
  11. #define MAX_BUFFER 512
  12. typedef struct sockaddr SSA;
  13. char timebuffer[50];  //存储时间
  14. char readbuffer[MAX_BUFFER];   //存储客户端数据
  15. time_t tick;
  16. //任务类
  17. class task
  18. {
  19. private:
  20. int connfd;  //与客户端连接的文件描述符
  21. public:
  22. task(int conn) : connfd(conn)
  23. {
  24. }
  25. ~task(){}
  26. void doit()  //线程池调用函数
  27. {
  28. size_t readsize;
  29. while((readsize = read(connfd, readbuffer, MAX_BUFFER)) > 0)  //读取客户端数据
  30. {
  31. printf("%ld get %dbyte\n",(unsigned long)pthread_self()
  32. , (int)readsize);   //测试用
  33. if(readsize == -1)  //read出错
  34. {
  35. printf("errno is %s\n", strerror(errno)); //这里输出"onnection reset by peer"
  36. continue;
  37. }
  38. readbuffer[readsize] = '\0';
  39. tick = time(NULL); //获取时间
  40. snprintf(timebuffer, sizeof(timebuffer), "time : %.24s\r\n",
  41. ctime(&tick));
  42. strcat(readbuffer, timebuffer);  //时间与客户数据连接到一起
  43. write(connfd, readbuffer, strlen(readbuffer));  //发送给客户端
  44. }
  45. //  printf("close the connfd\n");
  46. //  fflush(stdout);
  47. close(connfd);
  48. }
  49. };
  50. int main(int argc, char *argv[])
  51. {
  52. if(argc != 2)
  53. {
  54. printf("uasge : %s port", argv[0]);
  55. exit(-1);
  56. }
  57. int sockfd, connfd;
  58. struct sockaddr_in serv_addr, cli_addr;
  59. int port = atoi(argv[1]);
  60. //初始化sockaddr_in
  61. serv_addr.sin_family = AF_INET;
  62. serv_addr.sin_port = htons(port);
  63. serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);  //允许任何人连接
  64. //创建套接字
  65. sockfd = socket(AF_INET, SOCK_STREAM, 0);
  66. if(sockfd < 0)
  67. {
  68. printf("socket error' n");
  69. exit(-1);
  70. }
  71. //绑定
  72. bind(sockfd, (SSA *)&serv_addr, sizeof(serv_addr));
  73. //监听套接字
  74. listen(sockfd, 6);
  75. //创建线程池
  76. threadpool<task> pool(60, 100);
  77. pool.start();  //开启线程池
  78. while(1)
  79. {
  80. socklen_t len = sizeof(cli_addr);
  81. connfd = accept(sockfd, (SSA *)&cli_addr, &len);  //接受连接
  82. task *ta = new task(connfd);   //新建任务
  83. char buf[20];
  84. printf("IP %s conn\n", inet_ntop(AF_INET, &cli_addr.sin_addr, buf,
  85. sizeof(buf)));
  86. while(!pool.append_task(ta))  //添加任务到任务队列
  87. printf("loop\n"); //测试用
  88. }
  89. return 0;
  90. }

下面的是客户端的代码:

[cpp] view plain copy
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <arpa/inet.h>
  4. #include <string.h>
  5. #include <sys/types.h>
  6. #include <unistd.h>
  7. #include <netinet/in.h>
  8. #include <stdlib.h>
  9. int main(int argc, char *argv[])
  10. {
  11. if(argc != 3) //参数不对,退出
  12. {
  13. printf("usage: %s ip port\n", argv[0]);
  14. exit(-1);
  15. }
  16. int sockfd;
  17. struct sockaddr_in serv_addr;
  18. int port = atoi(argv[2]);  //将字符串的端口转换称int
  19. //初始化服务端的端口和IP地址
  20. serv_addr.sin_family = AF_INET;
  21. serv_addr.sin_port = htons(port);  //将主机字节序转换称网络字节序
  22. inet_pton(AF_INET, argv[1], &serv_addr.sin_addr);
  23. //创建套接字
  24. sockfd = socket(AF_INET, SOCK_STREAM, 0);
  25. //连接
  26. connect(sockfd, (struct sockaddr *)&serv_addr,
  27. sizeof(serv_addr));
  28. char buffer[50];
  29. write(sockfd, "hello\n", 6);  //写数据
  30. shutdown(sockfd, SHUT_WR);  //解释在下面
  31. size_t num = read(sockfd, buffer, sizeof(buffer));  //读数据
  32. buffer[num] = '\0';
  33. printf("read: %s\n", buffer);
  34. shutdown(sockfd, SHUT_RD);
  35. //    close(sockfd);
  36. return 0;
  37. }

客户端一开始我使用的是最后来个close的,就是注释那部分,但是多个连接同时来的时候,服务端会出错,具体的出错信息是:Connection reset by peer,重新执行read之后,得到Hello的个数没有少,也就是客户端发送的个数。

然而我客户端写完数据,就关闭写端,读取完数据,再关闭读端,就不会出现这样的错误。

具体原因还不是很清楚,网上没有查找到具体的答案。求大神来解答!!~~

==============================================

终于知道原因了,出错的是在服务端的read函数,read返回-1,而在客户端,发送完数据,就shutdown写端,发送完数据,就会发送FIN包,服务端read返回0,因为read不止被调用一次,第一次读取完数据之后,继续读取,可是客户端没有数据可读,就会出错,而提前关闭客户端写端,所以read那里的WHILE退出,就没有了出错的信息。

同时写了两个shell文件来测试:

[html] view plain copy
  1. #!/bin/bash
  2. for i in `seq 2000`
  3. do
  4. ./client.out 127.0.0.1 8989
  5. done

循环 执行2000次。

第二个shell文件:

[html] view plain copy
  1. #!/bin/bash
  2. ./loop.sh > file1 &
  3. ./loop.sh > file2 &
  4. ./loop.sh > file3 &
  5. ./loop.sh > file4 &
  6. ./loop.sh > file5 &
  7. wait

开启5个进程来返问。

执行第二个shell文件

最终,耗时为:

[html] view plain copy
  1. real    0m7.589s
  2. user    0m0.460s
  3. sys 0m1.944s

而且五个File文件中,有Hello的行数数都为2000.

下一篇是实现一个简单小型的web服务器。

Linux C++ 回射服务器相关推荐

  1. linux——回射服务器

    回射服务器即客户端发送一段数据给服务器,服务器再将这段数据原封不动的发送给客户端,原理很简单,原理图如下: 以TCP协议为例,客户端.服务器代码如下: ** 服务器: ** #include < ...

  2. LIBUV学习笔记(三)libuv中pipe/tty相关操作以及一个简单的unix域回射服务器/客户端例子...

    uv_pipe_t - Pipe handle Pipe handles provide an abstraction over local domain sockets on Unix and na ...

  3. 《UNP》随笔——“实现一个简单的回射服务器”存在的不足(信号处理)

    尽管实现了一个简单的回射服务器,但依旧存在一些不足: 服务端的子进程结束的时候,由于父进程未对子进程发送的SIGCHLD信号进行处理,会导致子进程进入僵死状态.这一点该如何解决? 客户端A向服务端B发 ...

  4. 一个简单的回射服务器

    本文编写了一个初步的简单的回射服务器例子.基本内容书上都能找到,认真看书就行了,所以尽量讲一些自己认为应该注意的地方. 功能: 客户端从标准输入读入一行文本,写给服务器:服务器读入这行文本,并回射给客 ...

  5. TCP echo_server(C++)回射服务器实现以及问题记录

    TCP echo_server(C++)回射服务器实现以及问题记录 基本运行方式: 客户端接收用户输入的字符串并发送到服务器端 服务器端将接收的字符串数据传回客户端 服务器端和客户端之间的字符串回射一 ...

  6. UNIX TCP回射服务器/客户端之使用epoll模型的服务器

    程序简介:这是一个运用epoll系列函数进行IO复用的服务器模型.它是目前UNIX与LINUX平台上效率最高,最受欢迎的IO复用传输模型. 其他的不说了,直接粘贴代码吧! 服务器端: #include ...

  7. Linux——回射服务器多并发(多线程)

    多线程与多进程的做法区别不大,思路一样,都是执行两个死循环,一个循环等待客户端连接,一个循环与客户端通信.多进程的方式请点此处 服务器 #include <sys/socket.h> #i ...

  8. linux——回射服务器多并发(多进程)

    多并发原理如图,多个客户端连接一个服务器,无论哪个客户端发送数据给服务器,服务器都能把数据准确的返回给这个客户端. 在socket编程中,socket这种文件描述符被默认设置为阻塞,故而read函数和 ...

  9. Linux非阻塞IO(八)使用epoll重新实现非阻塞的回射服务器

    2019独角兽企业重金招聘Python工程师标准>>> 本文无太多内容,主要是几个前面提到过的注意点: 一是epoll的fd需要重新装填.我们将tcp_connection_t的指针 ...

最新文章

  1. python基础——logging、OS、sys、random、string模块(0424)
  2. swift--添加新手引导页
  3. 计算机应用基础授课提纲,《计算机应用基础》讲授提纲(1).ppt
  4. internet explorer 无法打开 Internet站点 已中止操作
  5. Lotus Sametime Server R8.x 标准版部署排错
  6. 华为机试HJ62:查找输入整数二进制中1的个数
  7. Linux基础命令---显示文本grep
  8. String是java中的基本数据类型吗
  9. Windows10下安装linux(Utunbu)双系统
  10. 典型微型计算机控制系统的实例,微型计算机控制技术
  11. 计算机网络教室建设方案,计算机网络教室设计方案汇总.doc
  12. 科学家做一个实验,我就得胖三斤?
  13. [Hive SQL] 实现分组排序、分组topN
  14. 条令考试小程序辅助器_微信小程序条令考试刷分 微信小程序答题刷分软件
  15. java 校验银行卡号_Java之——基于Luhn算法的银行卡卡号的格式校验
  16. matlab gui输入函数,紧急求助!关于matlab中GUI用户图形界面通过edit输入调用函数问题!...
  17. Java代码混淆工具ProGuard
  18. 如何计算游戏客户端与服务器之间的时间延迟?
  19. 使用飞桨PaddleHub实现将视频动作转化为皮影戏
  20. 有了Forter ,中国的跨境电商们可以安心做生意了

热门文章

  1. Windows 自启动总结《转》
  2. jquery获得下拉框的值
  3. 用动画切换按钮的状态
  4. 今天开始学C#.NET
  5. c语言中栈堆,C语言中堆和栈的区别
  6. swagge php token,swagger在thinkphp6的使用方式
  7. 华为智能手表与鸿蒙,不再是大号手环!华为鸿蒙手表来了:要和苹果抢生态?...
  8. linux 修改jmeter内存溢出,jmeter本机内存溢出如何修改?
  9. 南岸焊接机器人厂_造船三部高效焊接工艺技术年鉴
  10. go返回多个值和python返回多个值对比