1. 循环服务器
-
一次只能处理一个客户端,等该客户端退出后,才能处理下一个客户端
-
缺点:循环服务器所处理的客户端不能有耗时操作
i. 模型
sfd = socket(); bind(); listen(); while(1) { newfd = accept(); while(1) { recv(); send(); } close(newfd); } close(sfd);
ii. 代码示例
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <unistd.h> #define ERR_MSG(msg) do{\ printf("line = %d\n", __LINE__);\ perror(msg); \ }while(0) #define PORT 6666 #define IP "192.168.1.12" //ifconfig查找到本机IP int main(int argc, const char *argv[]) { //1.创建字节流式套接字 int sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd < 0) { ERR_MSG("socket"); return -1; } //允许端口快速重用 int reuse = 1; if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))<0) { ERR_MSG("setsockopt"); return -1; } //绑定IP和端口 struct sockaddr_in sin; sin.sin_family = AF_INET; //地址族 sin.sin_port = htons(PORT); //端口号的网络字节序 sin.sin_addr.s_addr = inet_addr(IP); //IP地址的网络字节序 if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0) { ERR_MSG("bind"); return -1; } printf("绑定成功\n"); //listen 设置被动监听状态 if(listen(sfd, 10) < 0) { ERR_MSG("listen"); return -1; } printf("listen success\n"); struct sockaddr_in cin; socklen_t addrlen = sizeof(cin); while(1) { //accept int newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen); if(newfd < 0) { ERR_MSG("accept"); return -1; } printf("[%s:%d] newfd = %d\n", inet_ntoa(cin.sin_addr),ntohs(cin.sin_port) ,newfd); char buf[128] = ""; ssize_t res = 0; while(1) { bzero(buf, sizeof(buf)); res