网络模型:阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO

阻塞IO:


服务端代码:有客户端连接过来就会开起一个线程,这个线程去处理与此客户的数据收发,没有数据就会阻塞在accept那里

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string>
#include <memory.h>
#include <unistd.h>
#include <pthread.h>

#define BUFFSIZE 1024
#define PORT 5588
using namespace std;

template<typename T>
void log(T msg)
{
	cout<<msg<<endl;
}

int initSocket(int port)
{
	int fd = socket(AF_INET, SOCK_STREAM, 0);

	struct sockaddr_in sockaddr_t;
	memset(&sockaddr_t, 0, sizeof(sockaddr_in));
	sockaddr_t.sin_family = AF_INET;
	sockaddr_t.sin_port = htons(port);
	sockaddr_t.sin_addr.s_addr = htonl(INADDR_ANY);

	int ret = bind(fd, (struct sockaddr*)&sockaddr_t, sizeof(sockaddr_t));
	if(ret < 0)
	{
		//assert(ret < 0);
		return -1;
	}

	ret = listen(fd, 5);
	if(ret < 0)
	{
		//assert(ret < 0);
		return -1;
	}
	return fd;
}

int readMsg(int fd,char* buff,int buffSize)
{
	int ret = read(fd, buff, buffSize );
	return ret;
}

int writeMsg(int fd, char* buff, int len)
{
	int ret = 0;
	int falg = 0;
	while(ret < len )
	{
		ret += write(fd, buff+ret, len-ret);

		if(++falg > 3)
		{
			log("writeMsg is timeout");
			return -1;
		}
	}
	return 0;
}

void* pool(void* fd)
{
	int acceptfd = *((int *)fd);
	char readBuff[BUFFSIZE];
	while(1)
	{
		int ret = readMsg(acceptfd, readBuff, BUFFSIZE);
		log(readBuff);
		if(ret < 0)
		{
			close(acceptfd);
			printf("%s\n", "readMsg is error");
			continue;
		}
		ret = writeMsg(acceptfd, readBuff, strlen(readBuff));
		if(ret < 0)
		{
			log("writeMsg is error");
			close(acceptfd);
			continue;
		}
	}
}

int acceptSock(int fd)
{
	struct sockaddr_in clientAddr;
	socklen_t addrLen = sizeof(clientAddr);
	int acceptfd;
	char readBuff[BUFFSIZE];
	while(true)
	{
		memset(readBuff, 0, sizeof(readBuff));
		acceptfd = accept(fd, (struct sockaddr*)&clientAddr, &addrLen);
		if(acceptfd < 0)
		{
			continue;
		}
		printf("%s\t %d\n", "have a client connect:",acceptfd);
		pthread_t thread;
		int ret = pthread_create(&thread,NULL, pool,(void*)&acceptfd);
		log(thread);
	}
}


int main(int argc, char const *argv[])
{
	int fd;
	fd = initSocket(PORT);
	if(fd < 0)
	{
		return 0;
	}
	if(acceptSock(fd)<0)
	{
		exit(0);
	}
	return 0;
}

非阻塞IO:

当前进程调用recv(同上)时,不管有没有数据到来,都返回,然后执行下面,所以要进行轮训去查看有没有数据到来,这样容易造成忙等待,这种用法叫少,一般使用阻塞IO,可以用fcntl(fd,F_SETFL,flag|O_NONBLOCK)设置

设置非阻塞

void activate_nonblock(int fd)
{
    int ret;
    int flags=fcntl(fd,F_GETFL);
    if(flags == -1)
    {
        ERR_EXIT("fcntl");    
    }
    flags |= O_NONBLOCK;
    ret = fcntl(fd,F_SETFL,flags);
    if(ret ==-1)
    {
        ERR_EXIT("fcntl");
    }
    
}



IO复用:

select()可以管理多个文件描述符,设置关注事件,关注事件到来返回,调用recv读取数据

当使用阻塞IO时,没有数据到来时就会阻塞,如果使用select就会使阻塞提前到select,根据select判断是否有数据到来



信号驱动IO

建立信号驱动程序,调用sigactive注册信号,如果有数据到来就会触发SIGIO信号,接收信号判断是否是有数据到来然后再掉用recv接收数据




异步IO:

用户掉用aio_read,不论内核缓冲区有没有数据到来都会返回,当有数据到来的时候会以信号或其他方式通知用户



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值