listenfd = socket(…);
bind(listenfd,…);
listen(listenfd,…);
for ( ; ; ) {
connfd = accept(listenfd, …);
if (( pid = fork( )) == 0) {
recv(connfd,…);
send(connfd,…);
}
else
close(connfd);
}
根据上面的程序,对以下说法判断对错
a. 这是一个并发服务器( 对 )
b. 在任何时候,该服务器只能处理一个客户端的请求( 错 )
c. 随着服务器端接受越来越多的请求,connfd的值变得越来越大( 错 值不变 )
linux@ubuntu:~/projects/Level6day4_server_process/bin/x64/Debug$ ./Level6day4_server_process.out fd_client is :4 Clinet(192.168.0.158:43822) is connected! handler thread: newfd =4 message is:hELLo wOLd!!! message is:hELLo wOLd!!! fd_client is :4 Clinet(192.168.0.158:43824) is connected! handler thread: newfd =4 message is:hELLo wOLd!!! message is:hELLo wOLd!!! message is:hELLo wOLd!!! message is:hELLo wOLd!!! message is:hELLo wOLd!!! fd_client is :4 Clinet(192.168.0.158:43826) is connected! handler thread: newfd =4 message is:hELLo wOLd... message is:hELLo wOLd!!!
可以看到 'fd_client is :4 ' ,fd_client的值一直保持不变。
(作业要求:做作业的时候不要再翻看视频上的教程,对函数理解不明白的全部通过man手册去查看,
自己思考框架,使用makefile编译,然后将测试的记录和结果添加到readme.txt文件中提交上来,代码实现完成测试通过后
再提交作业,网络部分学习不写代码不测试看不出问题的,良好的习惯帮助你们快速成长。)
#include <cstdio> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> #include <pthread.h> #include <errno.h> #define SERV_PORT 5050 #define SERV_IP_ADDR "192.168.0.158" void* func_recall(void* arg); char botton[64]; int main() { int fd = -1; int result = 0,i=0; struct sockaddr_in mysockaddr; struct sockaddr_in clientscokaddr; socklen_t clientaddrlen; static pthread_t nptd; /* 1. 创建socket fd */ fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); return -1; } /*优化4: 允许绑定地址快速重用 */ int b_reuse = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &b_reuse, sizeof(int)); /*2. 绑定 */ /*2.1 填充struct sockaddr_in结构体变量 */ bzero((void*)&mysockaddr, sizeof(mysockaddr)); mysockaddr.sin_family = AF_INET; mysockaddr.sin_port = htons(SERV_PORT);//网络字节序的端口号 #if 1 //mysockaddr.sin_addr.s_addr = inet_addr(SERV_IP_ADDR); mysockaddr.sin_addr.s_addr = htonl(INADDR_ANY); #else result = inet_pton(AF_INET, SERV_IP_ADDR, (void*)&mysockaddr.sin_addr); if (result != 1) { perror("inet_pton"); return -1; } #endif /*2.2 绑定 */ result = bind(fd, (struct sockaddr*)&mysockaddr, sizeof(mysockaddr)); if (result != 0) { perror("bind"); return -1; } /*3. 调用listen()把主动套接字变成被动套接字 */ result = listen(fd, 5); if (result != 0) { perror("listen"); return -1; } /*4. 阻塞等待客户端连接请求 */ /*优化2:通过程序获取刚建立连接的socket的客户端的IP地址和端口号*/ int fd_client; while (1) { bzero((void*)&clientscokaddr, sizeof(clientscokaddr)); fd_client = accept(fd, (struct sockaddr*)&clientscokaddr, &clientaddrlen); if (-1 == result) { perror("accpet"); return 0; } char ipv4_addr[16]; if (!inet_ntop(AF_INET, (void*)&clientscokaddr.sin_addr, ipv4_addr, clientaddrlen)) { perror("inet_ntop"); return -1; } printf("Clinet(%s:%d) is connected!\n", ipv4_addr, ntohs(clientscokaddr.sin_port)); result = pthread_create(&nptd, 0, func_recall, (void*)&fd_client); if (result != 0) { perror("pthread_create"); return -1; } i++; } close(fd); close(fd_client); return 0; } void* func_recall(void* arg) { int result = 0; int newfd = *(int*)arg; printf("handler thread: newfd =%d\n", newfd); //..和newfd进行数据读写 char buf[BUFSIZ]; while (1) { bzero(buf, BUFSIZ); do { result = read(newfd, buf, BUFSIZ - 1); } while (result < 0 && EINTR == errno); if (result < 0) { perror("read"); break; } if (!result) break; printf("message is:%s\n", buf); } close(newfd); return 0; }
--------------------------------------------分割线---------------------------------------------------------
#include <cstdio> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <sys/stat.h> #include <unistd.h> #include <errno.h> #define SERV_PORT 5050 #define SERV_IP_ADDR "192.168.0.158" int main() { int fd = -1; int result = 0; struct sockaddr_in mysockaddr; char MESSAGE[] = "hELLo wOLd!!!\n"; /* 1. 创建socket fd */ fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); return -1; } /*2.连接服务器 */ /*2.1 填充struct sockaddr_in结构体变量 */ bzero((void*)&mysockaddr, sizeof(mysockaddr)); mysockaddr.sin_family = AF_INET; mysockaddr.sin_port = htons(SERV_PORT); //网络字节序的端口号 #if 0 mysockaddr.sin_addr.s_addr = inet_addr(SERV_IP_ADDR); #else result = inet_pton(AF_INET, SERV_IP_ADDR, (void*)&mysockaddr.sin_addr); if (result != 1) { perror("inet_pton"); return -1; } #endif /*2.2 connect 链接服务端*/ result = connect(fd, (struct sockaddr*)&mysockaddr, sizeof(mysockaddr)); if (result != 0) { perror("connect"); return -1; } printf("Client staring...OK!\n"); /*3. 读写数据 */ while (1) { do { result = write(fd, (void*)MESSAGE, sizeof(MESSAGE)); } while (result < 0 && EINTR == errno); //判断是否阻塞了 sleep(10); } close(fd); return 0; }
gcc -o server *.cpp -lpthread -Wall
gcc -o client *.cpp -Wall