本文共 3791 字,大约阅读时间需要 12 分钟。
http://blog.csdn.net/qq_25425023/article/details/53914820
回射服务器就是服务端将客户端的数据发送回去。
我实现的回射服务器返回增加了时间。
服务端代码,可以很容易看懂:
- #include <sys/socket.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <time.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <stdlib.h>
-
- #include "../thread_pool.h" //在上一篇博客中
-
- #define MAX_BUFFER 512
-
- typedef struct sockaddr SSA;
-
- char timebuffer[50];
- char readbuffer[MAX_BUFFER];
- time_t tick;
-
- class task
- {
- private:
- int connfd;
- public:
- task(int conn) : connfd(conn)
- {
- }
- ~task(){}
-
- void doit()
- {
- size_t readsize;
- while((readsize = read(connfd, readbuffer, MAX_BUFFER)) > 0)
- {
- printf("%ld get %dbyte\n",(unsigned long)pthread_self()
- , (int)readsize);
- if(readsize == -1)
- {
- printf("errno is %s\n", strerror(errno));
- continue;
- }
- readbuffer[readsize] = '\0';
- tick = time(NULL);
- snprintf(timebuffer, sizeof(timebuffer), "time : %.24s\r\n",
- ctime(&tick));
- strcat(readbuffer, timebuffer);
-
- write(connfd, readbuffer, strlen(readbuffer));
- }
-
-
-
- close(connfd);
- }
- };
-
- int main(int argc, char *argv[])
- {
- if(argc != 2)
- {
- printf("uasge : %s port", argv[0]);
- exit(-1);
- }
- int sockfd, connfd;
- struct sockaddr_in serv_addr, cli_addr;
- int port = atoi(argv[1]);
-
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(port);
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if(sockfd < 0)
- {
- printf("socket error' n");
- exit(-1);
- }
-
- bind(sockfd, (SSA *)&serv_addr, sizeof(serv_addr));
-
- listen(sockfd, 6);
-
- threadpool<task> pool(60, 100);
- pool.start();
- while(1)
- {
- socklen_t len = sizeof(cli_addr);
- connfd = accept(sockfd, (SSA *)&cli_addr, &len);
- task *ta = new task(connfd);
- char buf[20];
- printf("IP %s conn\n", inet_ntop(AF_INET, &cli_addr.sin_addr, buf,
- sizeof(buf)));
- while(!pool.append_task(ta))
- printf("loop\n");
- }
- return 0;
- }
下面的是客户端的代码:
- #include <stdio.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <string.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <netinet/in.h>
- #include <stdlib.h>
-
- int main(int argc, char *argv[])
- {
- if(argc != 3)
- {
- printf("usage: %s ip port\n", argv[0]);
- exit(-1);
- }
- int sockfd;
- struct sockaddr_in serv_addr;
- int port = atoi(argv[2]);
-
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(port);
- inet_pton(AF_INET, argv[1], &serv_addr.sin_addr);
-
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
- connect(sockfd, (struct sockaddr *)&serv_addr,
- sizeof(serv_addr));
- char buffer[50];
- write(sockfd, "hello\n", 6);
- shutdown(sockfd, SHUT_WR);
- size_t num = read(sockfd, buffer, sizeof(buffer));
- buffer[num] = '\0';
- printf("read: %s\n", buffer);
- shutdown(sockfd, SHUT_RD);
-
- return 0;
- }
客户端一开始我使用的是最后来个close的,就是注释那部分,但是多个连接同时来的时候,服务端会出错,具体的出错信息是:Connection reset by peer,重新执行read之后,得到Hello的个数没有少,也就是客户端发送的个数。 然而我客户端写完数据,就关闭写端,读取完数据,再关闭读端,就不会出现这样的错误。
具体原因还不是很清楚,网上没有查找到具体的答案。求大神来解答!!~~
==============================================
终于知道原因了,出错的是在服务端的read函数,read返回-1,而在客户端,发送完数据,就shutdown写端,发送完数据,就会发送FIN包,服务端read返回0,因为read不止被调用一次,第一次读取完数据之后,继续读取,可是客户端没有数据可读,就会出错,而提前关闭客户端写端,所以read那里的WHILE退出,就没有了出错的信息。
同时写了两个shell文件来测试:
- #!/bin/bash
-
- for i in `seq 2000`
- do
- ./client.out 127.0.0.1 8989
- done
循环 执行2000次。 第二个shell文件:
- #!/bin/bash
-
- ./loop.sh > file1 &
- ./loop.sh > file2 &
- ./loop.sh > file3 &
- ./loop.sh > file4 &
- ./loop.sh > file5 &
- wait
开启5个进程来返问。 执行第二个shell文件
最终,耗时为:
- real 0m7.589s
- user 0m0.460s
- sys 0m1.944s
而且五个File文件中,有Hello的行数数都为2000. 下一篇是实现一个简单小型的web服务器。