1.网络IO与select学习

流程:
1.创建listenfd 套接字 socket(AF_INET,SOCK_STREAM,0);
SOCK_STREAM 流的形式 TCP
2.创建地址族
Struct sockaddr_in servaddr;
Servaddr.sin_family =AN_INET; //IPV4
Servaddr.sin_addr.s_addr = htol(INADDR_ANY); // 0.0.0.0
Server.sin_port = htons(9999) // 端口
3.绑定端口
Bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
绑定 监听 地址族 地址族长度
4.创建一个客户端
Struct sockaddr_in clientfd;
Socklen_t len = sizeof(client);
5.接收
Int clientfd = accept(client,(struct sockaddr *)&client,&len);

Listen accept
Recv send

为什么是单次的,因为默认是阻塞的FD,没有数据不返回,一直在等
设置accept非阻塞:
Int flag = fcntl(listenfd,F_GETFL, 0 ); //获取当前模式
Flag |= O_NONBLOCK;
Fcntl(listenfd,F_SETFL,flag);

设置accept非阻塞后,结果值直接-1,并且永远返回不到。
因为非阻塞,直接返回了,还没有连接就返回了,除非用循环一直获取

发送数据,有时候可以收到,有时候收不到
结论:send返回正数,不等于发送成功
Send只是吧数据放入缓存,并没有发送出去

问题
1.一个客户端连接并且能够发送,另一个客户端能建立连接但是不能发送
2.当断开连接时,会循环recv,并且返回值为0
3.只能连接1次,不能再次连接
1的解法
原因:因为没有执行accept,每个客户端都要accept 但是建立连接不需要accept
解法:1.多线程或者多进程

一请求一线程,或者一请求一进程
一个线程只为一个fd服务
优点:逻辑简单
缺点:消耗内存
2.IO多路复用
2的解法
Recv返回0代表客户端断开(客户端调用close),

查看TCP 端口网络 netstat -anop|grep 端口号
所以 ,我们自己关闭close即可
Close的库是<unistd.h>

思考:单线程的情况下,多个客户端连接没有问题
1.无法进行accept

IO复用 检测IO是否有事件
select 管理所有IO

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>

#include <unistd.h>

#include <pthread.h>


#define BUFFER_LENGTH	128

// listenfd clientfd
struct sock_item{ // 用户 处理函数
	int fd; // clientfd
	char *rbuffer;//  数组处理超大字符串
	int rlength;
	char *wbuffer;
	int wlength;

	int event; //  读事件还是写事件
	void  (*recv_cb)(int fd,char *buffer,int lenght);
	void  (*send_cb)(int fd,char *buffer,int lenght);
	
	void  (*accept_cb)(int fd,char *buffer,int lenght);
}

struct reactor{
	int epfd;
}

// thread --> fd
void *routine(void *arg) {

	int clientfd = *(int *)arg;

	while (1) {
		
		unsigned char buffer[BUFFER_LENGTH] = {0};
		int ret = recv(clientfd, buffer, BUFFER_LENGTH, 0);
		if (ret == 0) {
			close(clientfd);
			break;
			
		}
		printf("buffer : %s, ret: %d\n", buffer, ret);

		ret = send(clientfd, buffer, ret, 0); // 

	}

}

// socket --> 
// bash --> execve("./server", "");
// 
// 0, 1, 2
// stdin, stdout, stderr
int main() {

// block
	int listenfd = socket(AF_INET, SOCK_STREAM, 0);  // 
	if (listenfd == -1) return -1;
// listenfd
	struct sockaddr_in servaddr;
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(9999);

	if (-1 == bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) {
		return -2;
	}

#if 0 // nonblock
	int flag = fcntl(listenfd, F_GETFL, 0);
	flag |= O_NONBLOCK;
	fcntl(listenfd, F_SETFL, flag);
#endif

	listen(listenfd, 10);

#if 0
	// int 
	struct sockaddr_in client;
	socklen_t len = sizeof(client);
	int clientfd = accept(listenfd, (struct sockaddr*)&client, &len);

	unsigned char buffer[BUFFER_LENGTH] = {0};
	int ret = recv(clientfd, buffer, BUFFER_LENGTH, 0);
	if (ret == 0) {
		close(clientfd);
		
	}
	printf("buffer : %s, ret: %d\n", buffer, ret);

	ret = send(clientfd, buffer, ret, 0); // 

	//printf("sendbuffer : %d\n", ret);
#elif 0

	while (1) {

		
		struct sockaddr_in client;
		socklen_t len = sizeof(client);
		int clientfd = accept(listenfd, (struct sockaddr*)&client, &len);
		
		pthread_t threadid;
		pthread_create(&threadid, NULL, routine, &clientfd);

		//fork();

	}
	

#else

	fd_set rfds, wfds, rset, wset;

	FD_ZERO(&rfds);
	FD_SET(listenfd, &rfds);

	FD_ZERO(&wfds);

	int maxfd = listenfd;

	unsigned char buffer[BUFFER_LENGTH] = {0}; // 0 
	int ret = 0;

	// int fd, 
	while (1) {

		rset = rfds;
		wset = wfds;

		int nready = select(maxfd+1, &rset, &wset, NULL, NULL);
		if (FD_ISSET(listenfd, &rset)) {

			printf("listenfd --> \n");

			struct sockaddr_in client;
			socklen_t len = sizeof(client);
			int clientfd = accept(listenfd, (struct sockaddr*)&client, &len);
			
			FD_SET(clientfd, &rfds);

			if (clientfd > maxfd) maxfd = clientfd;

			
			
		} 
		
		int i = 0;
		for (i = listenfd+1; i <= maxfd;i ++) {

			if (FD_ISSET(i, &rset)) { //

				ret = recv(i, buffer, BUFFER_LENGTH, 0);
				if (ret == 0) {
					close(i);
					FD_CLR(i, &rfds);
					
				} else if (ret > 0) {
					printf("buffer : %s, ret: %d\n", buffer, ret);
					FD_SET(i, &wfds);
				}
				
			} else if (FD_ISSET(i, &wset)) {
				
				ret = send(i, buffer, ret, 0); // 
				
				FD_CLR(i, &wfds); //
				FD_SET(i, &rfds);
				

			}

		}
		
		// 

	}

#endif

#else
	int epollfd = epoll_create(1);
	//一个epollfd就是一个epoll池,一个用户可以创建多个epoll池
	// reactor就是多个epoll池
	struct epoll_event ev;
	ev.events =EPOLLIN;  //可读 存事件的性质
	ev.data.fd = listenfd;
	epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);
	// epfd   操作  EPOLL_CTL_DEL 删除,监听fd,事件

	while (1)
		{
		int nready = epoll_wait(epfd,enents,EVNETS_LENGTH,0);
		/* 最后一个是返回事件,  -1就是一直阻塞,
			有数据才返回 0就是立即返回
			单位:毫秒 1s = 1000ms

			nready  没数据返回0,有数据返回数据量
		*/ 
		int i = 0;
		for(i = 0; i < nready; i++) {
			int clientfd = events[i].data.fd;
			if(listenfd == clientfd){ //accept
				第一个要单独处理
				struct sockaddr_in client;
				socklen_t len = sizeof(client);
				int connfd = accept(listenfd, (struct sockaddr*)&client, &len);
				ev.events = EPOLLIN;
				ev.data.fd = connfd;
				epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);
				//  ev是存储fd信息,ctl是将事件与操作绑定
			}else{
				char buffer[BUFFER_LENGTH] = {0};
				int n= recv(clienfd,buffer,BUFFER_LENGTH,0);
				if(n > 0){
					buffer[n] = '\0';
					printf("recv: %s,n: %d\n",buffer,n);
					int j = 0;
					for(j = 0;j<BUFFER_LENGTH;j++){
						buffer[j] = 'A';
					}

					/*
					while(1){
						int sent = send(clientfd,buffer,BUFFER_LENGTH);
						// 当协议栈的缓冲区满了的时候,是穿不进去的
						// 所以send之前需要判断一下。
					}
					*/
					while(1) {
						int sent = send(clientfd, buffer, BUFFER_LENGTH, 0); //
						printf("sent: %d\n", sent);
						if (sent != BUFFER_LENGTH) break;
					}
					
				}
		}
	}
#endif
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
重写下面代码;timer_handle_t itcs_timer_init(timer_handle_t handle, timer_event_cb_t cb_event) { timer_priv_t *timer_priv = handle; if (timer_priv->idx < 0 || timer_priv->idx >= CONFIG_TIMER_NUM) { return NULL; } set_clock_type("cpu-pclk"); // printf("enter timer init fun in driver\n"); uint32_t tempreg = 0; switch (timer_priv->idx) { case 0: timer_priv->base = ITCS_TIMER0_BASE; break; case 1: timer_priv->base = ITCS_TIMER1_BASE; break; default: break; } // printf("unit %d ,timeridx %d, base addr // %08x\n",timer_priv->idx,timer_priv->timeridx,timer_priv->base); switch (timer_priv->timeridx) { case 1: tempreg = readl(timer_priv->base + TIMER_CCR_CONTROL_C1); tempreg |= CCR_RST_ENABLE; writel(tempreg, timer_priv->base + TIMER_CCR_CONTROL_C1); tempreg = readl(timer_priv->base + TIMER_IER_C1); tempreg &= ~(IER_EVNT_ENABLE | IER_ITRV_ENABLE | IER_M1_ENABLE | IER_M2_ENABLE | IER_M3_ENABLE); writel(tempreg, timer_priv->base + TIMER_IER_C1); if (timer_priv->idx == 0) { timer_priv->irq = TTC0_TIMER1_IRQn; request_irq(TTC0_TIMER1_IRQn, itcs_timer_irq, "itcs_timer_irq01", timer_priv); } else { timer_priv->irq = TTC1_TIMER1_IRQn; request_irq(TTC1_TIMER1_IRQn, itcs_timer_irq, "itcs_timer_irq11", timer_priv); } break; case 2: tempreg = readl(timer_priv->base + TIMER_CCR_CONTROL_C2); tempreg |= CCR_RST_ENABLE; writel(tempreg, timer_priv->base + TIMER_CCR_CONTROL_C2); tempreg = readl(timer_priv->base + TIMER_IER_C2); tempreg &= ~(IER_EVNT_ENABLE | IER_ITRV_ENABLE | IER_M1_ENABLE | IER_M2_ENABLE | IER_M3_ENABLE); writel(tempreg, timer_priv->base + TIMER_IER_C2); if (timer_priv->idx == 0) { timer_priv->irq = TTC0_TIMER2_IRQn; request_irq(TTC0_TIMER2_IRQn, itcs_timer_irq, "itcs_timer_irq02", timer_priv); } else { timer_priv->irq = TTC1_TIMER2_IRQn; request_irq(TTC1_TIMER2_IRQn, itcs_timer_irq, "itcs_timer_irq12", timer_priv); } break; case 3: tempreg = readl(timer_priv->base + TIMER_CCR_CONTROL_C3); tempreg |= CCR_RST_ENABLE; writel(tempreg, timer_priv->base + TIMER_CCR_CONTROL_C3); tempreg = readl(timer_priv->base + TIMER_IER_C3); tempreg &= ~(IER_EVNT_ENABLE | IER_ITRV_ENABLE | IER_M1_ENABLE | IER_M2_ENABLE | IER_M3_ENABLE); writel(tempreg, timer_priv->base + TIMER_IER_C3); if (timer_priv->idx == 0) { timer_priv->irq = TTC0_TIMER3_IRQn; request_irq(TTC0_TIMER3_IRQn, itcs_timer_irq, "itcs_timer_irq03", timer_priv); // printf("unit timer1 ret=%08x , request irq3 success!\n",ret); } else { timer_priv->irq = TTC1_TIMER3_IRQn; request_irq(TTC1_TIMER3_IRQn, itcs_timer_irq, "itcs_timer_irq13", timer_priv); // printf("unit timer1 ret=%08x , request irq3 success!\n",ret); } break; default: return NULL; } timer_priv->cb_event = cb_event; // printf("init status irq id num:%d\n",timer_priv->irq); // printf("INIT TIMER %d Timer Count No %d SUCCESS\n", timer_priv->idx, // timer_priv->timeridx); return (timer_handle_t)timer_priv; }
02-17

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值