一、整体框架
二、 服务器
单循环服务器:同一时刻,只能处理一个客户端的任务
并发服务器:同一时刻,只能处理多个客户端的任务
UDP 是具备并发性的,是因为UDP是无连接的,所以处理器可以处理过来
TCP实际上是单循环的服务器,只能建立一对一连接,其他人不能再与其建立连接,之前只有一个套接字
现状为了实现并发,我们给每一个连接都给予一个套接字
三、TCP并发务器
3.1、多进程
执行流程:
- socket()
- bind()
- listen()
- accept()
- fork()
3.2、多线程
#include<head.h>
void *doSth(void *arg)
{
int connfd = *((int *)arg);
while(1)
{
char buff[1024] = {0};
ssize_t size = recv(connfd,buff,sizeof(buff),0);
if(size <= 0)
{
break;
}
printf("cli--------->%s\n",buff);
strcat(buff,"----->ok!");
send(connfd,buff,strlen(buff),0);
}
close(connfd);
}
int conct(const char *ip,unsigned short port)
{
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd == -1)
{
return -1;
}
struct sockaddr_in ser;
ser.sin_family = AF_INET;
ser.sin_port = htons(port);
ser.sin_addr.s_addr = inet_addr(ip);
int ret = bind(sockfd,(struct sockaddr *)&ser,sizeof(ser));
if(ret == -1)
{
perror("fail bind");
return -1;
}
ret = listen(sockfd,120);
if(ret ==-1)
{
return -1;
}
return sockfd;
}
int main(int agrc,char *agrv[])
{
int connfd = 0;
char buf[1024] = {0};
int ret;
pthread_t tid ;
int sockfd = conct("192.168.1.112",60000);
if(sockfd == -1)
{
return -1;
}
while(1)
{
connfd = accept(sockfd,NULL,NULL);
if(-1 == connfd)
{
return -1;
}
pthread_create(&tid,NULL,doSth,&connfd);
pthread_detach(tid);
}
return 0;
}
3.3、IO多路复用
多个读写复用一个进程(在Linux里面就是文件读写)
四、IO模型
4.1、阻塞IO
fgets,scanf,read,recv,getchar(用来实现多个IO同步的效果)
同步:具有先后顺序的效果
#include<head.h>
int main(int agrc,char *agrv[])
{
char buf[1024] = {0};
mkfifo("./fifo",0666);
int fd = open("./fifo",O_RDONLY);
int flag = fcntl(0,F_GETFL);
flag = flag & ~O_NONBLOCK;
fcntl(0,F_SETFL,flag);
while(1)
{
memset(buf,0,sizeof(buf));
fgets(buf,sizeof(buf),stdin);
printf("STDIN : %s\n",buf);
memset(buf,0,sizeof(buf));
read(fd,buf,sizeof(buf));
printf("buf = %s\n",buf);
}
close(fd);
return 0;
}
特点:
- CPU 占有率低
- 执行效率低
4.2、非阻塞IO
非阻塞就是访问内核,有数据带着数据返回,没有数据也带着返回
特点
- 使用轮询的方式实现
- CPU占有率高
实现:
1、获取原文件描述符的属性
2、增加非阻塞属性
3、设置新属性
#include<head.h>
void handle(int signo)
{
char buf[1024] = {0};
fgets(buf,sizeof(buf),stdin);
printf("STDIN : %s\n",buf);
}
int main(int agrc,char *agrv[])
{
signal(SIGIO,handle);
char buf[1024] = {0};
mkfifo("./fifo",0666);
int fd = open("./fifo",O_RDONLY);
int flag = fcntl(0,F_GETFL);
flag = flag | O_ASYNC;
fcntl(0,F_SETFL,flag);
fcntl(0,F_SETOWN,getpid());
while(1)
{
memset(buf,0,sizeof(buf));
read(fd,buf,sizeof(buf));
sleep(1);
printf("%s\n",buf);
}
close(fd);
return 0;
}
4.3、信号驱动IO
实现:(当终端有输入的时候应该会触发,发射信号,才会执行)
1、增加异步属性 O_ASYNC(异步),O_SYNC(同步)
2、关联信号和当前的进程
3、注册信号
特点:
1、异步通知io的方式,节省CPU
2、只能检测少量io
2、效率高
标签:return,int,TCP,char,并发,sockfd,服务器,sizeof,buf From: https://blog.csdn.net/2401_84308772/article/details/141614694