循环服务器:
单任务完成服务众多客户端的请求,待服务的客户端需排队等待服务。
优点: 简单、轻量、易于实现。
缺点: 服务效率不高,无法同时服务多个请求。一旦有客户端恶意占用服务时间,会导致排队的客户端无法接受服务。(基于UDP的echo服务器。)
(1)UDP 循环服务器
框架:
服务器端:
socket();
bind();
recvfrom();
sendto();
close();
客户端:
socket();
sendto();
recvfrom();
close();
代码实例(客户端发送请求,内容为TIME的字符串,服务器端进行判断后,将时间反馈给客户端。)
客户端代码:
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 8888 //设置端口号
#define BUFF_SIZE 1024
int main(int argc, const char *argv[])
{
int sockfd;//创建服务器套接字文件描述符
struct sockaddr_in server;//本地地址
char buff[BUFF_SIZE];//收发数据缓冲区
int n=0;//接收字符串长短
socklen_t len=0;//本地地址长度
sockfd = socket(AF_INET, SOCK_DGRAM, 0);//创建UDP套接字
/*初始化地址*/
memset(&server,0,sizeof(server));//清零
server.sin_family=AF_INET;//AF_INET协议族
server.sin_addr.s_addr=htonl(INADDR_ANY);//任意地址
server.sin_port=(SERVER_PORT);//服务器端口号
memset(buff,0,BUFF_SIZE);//清零
strcpy(buff,"TIME");//复制发送字符串
/*发送数据*/
if((sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&server,sizeof(server)))==-1)
{
perror("fail to sento");
exit(1);
}
memset(buff,0,BUFF_SIZE);//清零
/*接收数据*/
len=sizeof(server);
n=recvfrom(sockfd,buff,BUFF_SIZE,0,(struct sockaddr*)&server,&len);
if(n>0)
{
printf("TIME:%s",buff);//打印消息
}
close(sockfd);
return 0;
}
服务器端代码:
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 8888
#define BUFF_SIZE 1024
int main(int argc, const char *argv[])
{
int sockfd;//服务器套接字文件描述符
struct sockaddr_in local,to;//本地地址信息和发送方地址信息
char buff[BUFF_SIZE];//收发数据缓存区
int n=0;
time_t now;//时间
socklen_t len=sizeof(to);//发送方地址长度
sockfd=socket(AF_INET,SOCK_DGRAM,0);//建立UDP套接字
memset(&local,0,sizeof(local));//清零
local.sin_family=AF_INET;//AF_INET协议族
local.sin_addr.s_addr=htonl(INADDR_ANY);//任意本地地址
local.sin_port=(SERVER_PORT);//服务器端口
/*将套接字文件描述符绑定到本地地址和端口号*/
if((bind(sockfd,(struct sockaddr*)&local,sizeof(local)))==-1)
{
perror("fail to bind");
exit(1);
}
while(1)
{
memset(buff,0,BUFF_SIZE);//清零
n=recvfrom(sockfd,buff,BUFF_SIZE,0,(struct sockaddr*)&to,&len);//接收发送方数据
if(n>0&&!strncmp(buff,"TIME",4))//判断是否合法
{
memset(buff,0,BUFF_SIZE);//清零
now=time(NULL);//获取时间
sprintf(buff,"%24s\r\n",ctime(&now));//将时间复制如缓冲区
sendto(sockfd,buff,strlen(buff),0,(struct sockaddr*)&to,len);//发送数据
}
}
close(sockfd);
return 0;
}
(2)TCP循环服务器
框架:
客户端
socket();
connect();
send();
recv();
close();
服务器端
socket();
bind();
listen();
accept();
recv();
send();
close();
代码实例(与UDP相同)
客户端:
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 8889
#define BUFF_SIZE 1024
int main(int argc, const char *argv[])
{
int sockfd;//服务器套接字文件描述符
struct sockaddr_in server;//本地地址
char buff[BUFF_SIZE];//收发数据缓存区
int n=0;//接收字符串长度
/*建立TCP套接字*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立TCP套接字
/*初始化地址*/
memset(&server,0,sizeof(server));//清零
server.sin_family=AF_INET;//AF_INET协议族
server.sin_addr.s_addr=htonl(INADDR_ANY);//任意本地地址
server.sin_port=(SERVER_PORT);//服务器端口
/*连接服务器*/
connect(sockfd,(struct sockaddr*)&server,sizeof(server));
memset(buff,0,BUFF_SIZE);//清零
strcpy(buff,"TIME");//复制发送的字符串
/*发送数据*/
if((send(sockfd,buff,strlen(buff),0))==-1)
{
perror("fail to sent");
exit(1);
}
memset(buff,0,BUFF_SIZE);//清零
/*接收数据*/
n=recv(sockfd,buff,BUFF_SIZE,0);
if(n>0)
{
printf("TIME:%s",buff);
}
close(sockfd);
return 0;
}
服务器端:
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 8889//端口地址
#define BUFF_SIZE 1024
#define BACKLOG 5//监听队列长度
int main(int argc, const char *argv[])
{
int sockfd,connfd;//sockfd为服务器socket描述符,connfd为客户端的socket描述符
struct sockaddr_in local,to;//本地地址
char buff[BUFF_SIZE];//收发数据缓存区
int n=0;
time_t now;//时间
socklen_t len=sizeof(to);//
/*建立TCP套接字*/
sockfd=socket(AF_INET,SOCK_STREAM,0);
/*设置服务器地址*/
memset(&local,0,sizeof(local));
local.sin_family=AF_INET;
local.sin_addr.s_addr=htonl(INADDR_ANY);
local.sin_port=(SERVER_PORT);
/*绑定地址结构到套接字描述符*/
if((bind(sockfd,(struct sockaddr*)&local,sizeof(local)))==-1)
{
perror("fail to bind");
exit(1);
}
/*设置监听*/
listen(sockfd,BACKLOG);
while(1)
{
/*接收客户端连接*/
connfd=accept(sockfd,(struct sockaddr*)&to,&len);
memset(buff,0,BUFF_SIZE);
/*接收发送发数据*/
n=recv(connfd,buff,BUFF_SIZE,0);
if(n>0&&!strncmp(buff,"TIME",4))
{
memset(buff,0,BUFF_SIZE);
now=time(NULL);
sprintf(buff,"%24s\r\n",ctime(&now));
send(connfd,buff,strlen(buff),0);
}
close(connfd);
}
close(sockfd);
return 0;
}