服务器模型
在服务端中,服务器有一个listen函数。它用于等待客户端连接,把多个客户端放到等待队列当中。而服务器可以有多个连接请求,进行监听,可以取出一个连接请求,然后创建一个通信套接字与一个客户端进行通信(进行与客户端进行一对一通信)。
服务器(服务端)通常处理多个客户端通信,服务端则需要可以和多个客户端进行通信。
为了能够达到服务端与多个客户端进行通信,服务端程序需要有不同的处理方式 :
1、循环服务器模型
一次只与一个客户端进行通信,当与一个客户端通信完成后,再与下一个客户端进行通信。
也就是必须上一个完了才能进行下一个通信,由于listen()监听,则服务端会一直做监听(直到关闭
服务端的监听套接字),不管当前是否是在通信都一直在进行监听,然后只要有连接请求都放在等
待队列。
实现循环服务器,只需要多次accept从等待队列中获取新的连接请求进行通信,代码如下:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc,char * argv[])
{
int serverfd = socket(AF_INET,SOCK_STREAM,0);
if(serverfd < 0)
{
perror("socket error");
return 0;
}
//服务端的ip、port
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9999);
serveraddr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");
bind(serverfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
listen(serverfd,5);//监听套接字,检测客户端的连接,只要有客户端连接,就存放到等待队列
while(1)
{
struct sockaddr_in client;//用于存储客户端地址
socklen_t len;
int fd = accept(serverfd,(struct sockaddr *)&client,&len);//阻塞等待等待队列有客户端连接,建立连接,得到客户端
char buf[20];//通信
int num;
while(1)
{
bzero(buf,20);
num = read(fd,buf,20);
if(num > 0)
{
printf("server read ok,data is %s",buf);
}
write(fd,"ok\n",4);
if(strcmp(buf,"quit\n") == 0)
{
break;
}
}
close(fd);//关闭与客户端通信
}
//服务端不在进行通信,要关闭整个服务端才关闭监听套接字
close(serverfd);//关闭整个服务端,不能使用tcp,不能监听
return 0;
}
2、并发服务器模型
在服务器中,可以进行多个客户端的连接请求,同时进行通信接受一个客户端连接请求
后与客户端进行处理,还可以与其他客户端进行连接,可以同时与多个客户端进行操作。
实现处理多个则需要通过多进程或者多线程来实现,代码如下:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0)
{
perror("socket error");
return 0;
}
struct sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(9999);
serveraddr.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");
bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
listen(sockfd,5); //做多5个连接客户端,创建5个等待队列
while(1)
{
struct sockaddr_in clint;
socklen_t len;
int fd = accept(sockfd,(struct sockaddr *)&clint,&len);
if(fork() == 0)
{
//操作
}
close(fd);
}
colse(sockfd)
}
这两个服务器模型一个是串联工作,一个是并连工作,各有各的优势,不过常用的还是并连的这种。