基于uloop和usock的TCP客户端断线重连

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

解决TCP连接过程中意外中断的情况,暂无考虑长时间网络断掉。如果长时间网络断掉,建议起一个定时器来做定时连接


一、具备的基础

你要想看懂这个代码,首先你得了解一下uloop这个框架。网上资料很多,当然这个框架也不是那么完善,有一定的坑在,还是得需要多写写。其次,你得简单了解一下usock,不用那么细致。最后,你有个开发板,或者你装在ubunt上测试。

二、代码展示

代码如下:

/*
* 作者:笨笨熊
* 日期:2021/12/20
* 用途:
* 该程序主要是基于usock编程的客户端
* 主要是测试程序的断线重连,适合于TCP协议连接
*
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <asm/ioctl.h>
#include <sys/socket.h>
#include <libubox/usock.h>
#include "libubox/uloop.h"

#include "tool.h"

#define SERVER_IP "172.16.5.14"
#define SERVER_PORD "8888"

struct uloop_fd c_fd;  		 /*客户端接收数据句柄*/
struct uloop_timeout c_send; /*客户端定时发送句柄*/

char recv_buf[64];           /*数据接收缓冲区*/

/*重连函数*/
static int reconnect()
{

	int type = USOCK_TCP | USOCK_NOCLOEXEC | USOCK_IPV4ONLY;
	c_fd.fd = usock(type, SERVER_IP, SERVER_PORD); /* create a linker socket*/
	if (c_fd.fd < 0)
	{
		perror("usock error");
		return -1;
	}
	
	uloop_fd_add(&c_fd, ULOOP_READ);
	uloop_timeout_set(&c_send, 2000); //2s发一次
	
	return 0;
}
/*接收服务器数据*/
int clinet_recv(struct uloop_fd *sock, unsigned int events)
{
	int rev_len;
	rev_len = read(sock->fd, recv_buf, sizeof(recv_buf));
	if (rev_len > 0)
	{
		DEBUG_PRINT("Recv:%s Len:%d \n", recv_buf, rev_len);
		memset(recv_buf, 0, sizeof(recv_buf));
		write(sock->fd, "#", 1);
	}
	else
	{
		/*此时判断断开连接,进入重连*/
		DEBUG_PRINT("Recv  failed\n");
		goto error;
	}
	return 0;
error:
	if (sock->fd)
	{
		uloop_fd_delete(sock);
		close(sock->fd);
		sock->fd = -1;
		DEBUG_PRINT("Close client fd\n");
		uloop_timeout_cancel(&c_send);
		if (reconnect() < 0)
		{
			DEBUG_PRINT("ERROR: INIT FAILED\n");
		}
		else
		{
			DEBUG_PRINT("CONNECT SUCCESS!!!\n");
		}
	}
	return 0;
}
/*定时向服务器发送数据*/
static void c_send_timer(struct uloop_timeout *timer)
{
	int ret;
	DEBUG_PRINT("hello\n");
	ret = write(c_fd.fd, "hello", 5);
	if (ret < 0)
	{
		uloop_timeout_cancel(timer);
		DEBUG_PRINT("Cancel send \n");
	}
	uloop_timeout_set(&c_send, 2000); //2s发一次
}

static int client_init()
{

	int type = USOCK_TCP | USOCK_NOCLOEXEC | USOCK_IPV4ONLY;
	c_fd.fd = usock(type, SERVER_IP, SERVER_PORD); /* create a linker socket*/

	if (c_fd.fd < 0)
	{
		perror("usock");
		return -1;
	}
	/*客户端接收回调绑定*/
	c_fd.cb = clinet_recv;
	uloop_fd_add(&c_fd, ULOOP_READ);
	/*定时发送回调绑定*/
	c_send.cb = c_send_timer;
	uloop_timeout_set(&c_send, 2000); //2s发一次

	return 0;
}
int main()
{

	uloop_init();
	/*客户端初始化*/
	if (client_init() < 0)
	{
		DEBUG_PRINT("ERROR: INIT FAILED\n");
	}
	else
	{
		DEBUG_PRINT("CONNECT SUCCESS!!!\n");
	}
	uloop_run();

	close(c_fd.fd);
	uloop_done();
	return 0;
}

2.测试结果

客户端状况:
在这里插入图片描述
服务端状况
在这里插入图片描述


总结

没有太过细致的去帮大家分析一下,注释都已经写了。大家慢慢看吧。有什么问题也可以提问,我会及时回复。如果写的不好,也可以跟我说。如果代码有帮到你,麻烦点一个赞吧。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值