关于libuv接收大于指定长度数据包

关于libuv接收大于指定长度数据包

libuv接收数据:uv_alloc_buf分配多少大小内存空间,就接收多少大小的数据

uv_read_start

	static void uv_connection(uv_stream_t* server, int status){

		uv_session* uv_s = uv_session::create();


		uv_tcp_t* client = &uv_s->tcp_handler;
		memset(client, 0, sizeof(uv_tcp_t));
		uv_tcp_init(uv_default_loop(), client);
		client->data = (void*)uv_s;


		uv_accept(server, (uv_stream_t*)client);
		struct sockaddr_in addr;
		int len = sizeof(struct sockaddr_in);
		uv_tcp_getpeername(client, (sockaddr*)&addr, &len);


		uv_ip4_name(&addr, (char*)uv_s->c_address, 32);
		uv_s->c_port = ntohs(addr.sin_port);
		uv_s->socket_type = (int)server->data;


		printf("new client commings %s:%d\n", uv_s->c_address, uv_s->c_port);


		uv_read_start((uv_stream_t*)client, uv_alloc_buf, after_read);

	}

uv_alloc_buf

	static void uv_alloc_buf(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf){




		uv_session* s = (uv_session*)handle->data;

		printf("收到字节数为%d\n", s->recved);

		if (s->recved < RECV_LEN){
			*buf = uv_buf_init(s->recv_buf + s->recved, RECV_LEN - s->recved);
		}
		else{
			if (s->long_pkg == NULL){
				int pkg_size;
				int head_size;
				if (s->socket_type == WS_SOCKET && s->is_ws_shake){

					ws_protocol::read_ws_header((unsigned char*)s->recv_buf, s->recved, &pkg_size, &head_size);
					s->long_pkg_size = pkg_size;
					s->long_pkg = (char*)malloc(pkg_size);
					memcpy(s->long_pkg, s->recv_buf, s->recved);   //把原来存的数据移动到long_pkg里面

				}
				else{
					//TCP_SOCKET处理
					tcp_protocol::read_header((unsigned char*)s->recv_buf, s->recved, &pkg_size, &head_size);
					s->long_pkg_size = pkg_size;
					s->long_pkg = (char*)malloc(pkg_size);
					memcpy(s->long_pkg, s->recv_buf, s->recved);   //把原来存的数据移动到long_pkg里面


				}
			}
			*buf = uv_buf_init(s->long_pkg + s->recved, s->long_pkg_size - s->recved);

		}
	}

after_read

	static void after_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf){



		uv_session* s = (uv_session*)stream->data;
		if (nread < 0){
			s->close();
			return;
		}

		s->recved += nread;
		if (s->socket_type == WS_SOCKET){   //websocket
			if (s->is_ws_shake == 0){  //没有握手

				if (ws_protocol::ws_shake_hand((session*)s, s->recv_buf, s->recved)){
					s->is_ws_shake = 1;   //握手成功
					s->recved = 0;
				}
			}
			else{  //已经握手,可以收发数据了
				on_recv_ws_data(s);
			}
		}
		else{   //tcpsocket
			on_recv_tcp_data(s);
		}


	}

on_recv_ws_data接受数据后,如果收到的数据大于RECV_LEN定义的最大长度,比如定义最大长度RECV_LEN为10,但是却收到了15个字节数据,uv_alloc_buf分配多少长度,libuv内存就收到多少数据

Libuv收数据是这样的流程

第一步:如果有用户首次发数据过来(158888888888888159999999999999),就会首先触发uv_alloc_buf函数,这个时候收到的数据s->recved = 0,所以就会分配一个RECV_LEN(10)长度的内存s->recv_buf

第二步:等uv_alloc_buf分配完成内存后,触发after_read函数,接受数据,把数据保存到uv_alloc_buf分配的内存中去,这个时候只收到了10个字节的数据为(138888888888888)s->recved = 10,数据包长度pkg_size = 15,只收到了10字节后面还有5个字节没有收到,把数据放到s->recv_buf内存中

第三步:剩余用户发送的数据,会再次触发一次uv_read_start函数,通过uv_alloc_buf再次分配内存这个时候,s->recved < RECV_LEN 为 FALSE,就分配了s->long_pkg,从数据中读取数据包长度pkg_size为15(假设),就分配s->long_pkg的长度为15,把数据从s->recv_buf复制到s->long_pkg中

第四步:再次进入到after_read函数中s->recved = 15,再次读取数据包体长度为pkg_size = 15,处理完成后s->recved - pkg_size = 0,如果(s->recved == 0 && s->long_pkg != NULL),就把s->long_pkg内存释放掉,这样每次s->long_pkg只会处理一个完成的数据包,就不会存在收到多个大于RECV_LEN长度的数据包

第五步:下次再次接收数据的时候,就会重新分配s->recv_buf;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值