前言
1、在网络通信中,服务器端通常需要处理多个客户端,总体上采用两种模型来实现:循环服务器和并发服务器。
2、循环服务器是指服务器端依次处理每个客户端,直到当前客户端处理完毕,再处理下一个客户端
3、并发服务器是指服务器采用多任务机制(多进程或多线程),分别为每个客户端创建一个任务来处理
一、TCP下的循环服务器
1、工作流程:
(1)服务器端从连接请求队列中提取请求,建立连接并返回新的已连接套接字
(2)服务器端通过已连接套接字循环接收数据,处理并发送给客户端,直到客户端关闭连接
(3)服务器端关闭已连接的套接字,返回步骤1
//服务器端//
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
char buf[100]={0};//缓冲区
int n;
int fd=socket(AF_INET,SOCK_STREAM,0);//建立套接字
struct sockaddr_in myaddr;//定义addr结构体
myaddr.sin_family=AF_INET;
myaddr.sin_port=htons(8888);//端口号
myaddr.sin_addr.s_addr=htonl(INADDR_ANY);//自定义ip地址
int ret=bind(fd,(struct sockaddr*)&myaddr,sizeof(myaddr));//绑定ip地址和端口号
listen(fd,5);//设置连接数量
while(1)
{
int newfd=accept(fd,NULL,NULL);//收到连接后返回连接好后的描述符
while((n=recv(fd,buf,sizeof(buf),0))>0)
{
printf("buf is %s\n",buf);
send(newfd,buf,sizeof(buf),0);//发送数据
}
printf("client is closed\n");
close(newfd);//关闭连接描述符
}
close(fd);//关闭套接字描述符
}
//客户端//
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
int main(int argc,char *argv[])
{
int fd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in youraddr;
youraddr.sin_family=AF_INET;
youraddr.sin_port=htons(atoi(argv[1]));
youraddr.sin_addr.s_addr=inet_addr(argv[2]);
connect(fd,(struct sockaddr *)&youraddr,sizeof(youraddr));//发送链接请求
printf("连接成功!\n");
char buf[100];
while(1)
{
scanf("%s",buf);
send(fd,buf,sizeof(buf),0);
recv(fd,buf,sizeof(buf),0);
printf("ret is %s\n",buf);
}
close(fd);
}
二、TCP下的并发服务器
1、工作流程:
(1)服务器端主进程从连接请求队列中提取请求,建立连接并返回新的已连接套接字
(2)服务器端主进程创建线程为客户服务。客户端关闭连接时,子进程结束
(3)服务器端主进程关闭已连接套接字,返回步骤1
//服务器端//
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
void *recv_fun(void *p)
{
int fd=*(int *)p;
while(1)
{
char buf[100];
if(recv(fd,buf,sizeof(buf),0)<=0)
break;
printf("buf is %s\n",buf);
send(fd,buf,sizeof(buf),0);
}
}
int main()
{
int fd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in myaddr;
myaddr.sin_family=AF_INET;
myaddr.sin_port=htons(8888);
myaddr.sin_addr.s_addr=htonl(INADDR_ANY);
int ret=bind(fd,(struct sockaddr*)&myaddr,sizeof(myaddr));
listen(fd,5);
while(1)
{
pthread_t id;//定义线程变量
int newfd=accept(fd,NULL,NULL);
printf("new client %d\n",newfd);
pthread_create(&id,NULL,recv_fun,&newfd);//创建新线程
}
close(fd);
}
//客户端//
#include<stdio.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
int main(int argc,char *argv[])
{
int fd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in youraddr;
youraddr.sin_family=AF_INET;
youraddr.sin_port=htons(atoi(argv[1]));
youraddr.sin_addr.s_addr=inet_addr(argv[2]);
connect(fd,(struct sockaddr *)&youraddr,sizeof(youraddr));
printf("连接成功!\n");
char buf[100];
while(1)
{
scanf("%s",buf);
send(fd,buf,sizeof(buf),0);
recv(fd,buf,sizeof(buf),0);
printf("ret is %s\n",buf);
}
close(fd);
}