Linux使用Libubox中的ustream方向进行通信

Libubox中的ustream封装了socket的一些函数功能,使用更加方便和快捷;一般在OpenWrt环境中使用

原理

git://nbd.name/luci2/libubox.git

流程

连接成功后注册读写和状态回调函数

代码

//客户端//
#include "std.h"

/* 在TCP连接持续多少秒没有报文往来之后则开始发送探测报文 */
int tcp_keepalive_time = 5;
/* TCP keepalive探测包的发送间隔 */
int tcp_keepalive_intvl = 5;
/* 在tcp_keepalive_time之后没有收到对方确认,继续发送保活探测包的次数 */
int tcp_keepalive_probes = 3;

int fd = -1;
struct ustream_fd ufd;                      // uloop机制监听的结构体

static void notify_read_cb(struct ustream *s, int bytes)
{
    char *data = NULL;
    int len;

    data = ustream_get_read_buf(s, &len);
    printf("eason recv data:%d available len:%d", bytes, len);
    if(!data){
        printf("eason recv packet len is too short, wait more data");
        return;
    }

    ustream_consume(s, len);
}

/**************************************************************************************
* FunctionName   : notify_state_cb()
* Description    : uloop+ustream框架通知连接状态发生变化的回调,如果检测到对端断开则本地断开连接
* EntryParameter : 指向当前活跃的ustream的指针
* ReturnValue    : NULL
**************************************************************************************/
static void notify_state_cb(struct ustream *s)
{
    if (!s->eof) return;
    printf("eason misock client got eof!, pending:%d", s->w.data_bytes);
	close(fd);
}

/**************************************************************************************
* FunctionName   : notify_write_cb()
* Description    : uloop+ustream框架通知缓冲数据已经被写入到stream中
* EntryParameter : 指向当前活跃的ustream的指针
* ReturnValue    : NULL
**************************************************************************************/
static void notify_write_cb(struct ustream *s, int bytes)
{
    printf("eason misock client wrote:%d bytes, pending:%d", bytes, s->w.data_bytes);
}

static void setup_misock_client_ustream()
{
    ufd.stream.string_data  = false;
    ufd.stream.notify_read  = notify_read_cb;
    ufd.stream.notify_state = notify_state_cb;
    ufd.stream.notify_write = notify_write_cb;
    ustream_fd_init(&ufd, fd);
}

int main(void)
{
	struct sockaddr_in server;
	int optval;
    struct timeval tval;
    fd_set r_set, w_set;
    int rc = 0;
	
	// 1.创建
	if (0 > (fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)))
		err_exit("socket");
	
	// 2.模式
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); //设置非阻塞模式

	// 3.绑定

	// 4.连接
	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(8888);
	server.sin_addr.s_addr = inet_addr("192.168.201.130");
	if (0 > connect(fd, (struct sockaddr *)&server, sizeof(server)))
		err_exit("connect");
	printf("connect success!\n");


	/* 4.KEEPALIVE相关配置 */
	/*使能keepalive*/
	optval =1;
	setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
	/* 配置tcp_keepalive_time */
	optval = tcp_keepalive_time;
	setsockopt(fd, SOL_TCP, TCP_KEEPIDLE, &optval, sizeof(optval));
	/* 配置tcp_keepalive_intvl */
	optval = tcp_keepalive_intvl;
	setsockopt(fd, SOL_TCP, TCP_KEEPINTVL, &optval, sizeof(optval));
	/* 配置tcp_keepalive_probes */
	optval = tcp_keepalive_probes;
	setsockopt(fd, SOL_TCP, TCP_KEEPCNT, &optval, sizeof(optval));

	// 4.确定连接已经成功
	FD_ZERO(&r_set);
	FD_SET(fd, &r_set);
	FD_ZERO(&w_set);
	FD_SET(fd, &w_set);
	tval.tv_sec  = 1;
	tval.tv_usec = 0;

	rc = select(fd+1, &r_set, &w_set, NULL, &tval);
	if(rc <= 0){
		printf("eason fun=%s,line=%d", __FUNCTION__,__LINE__);
		goto RETURN_1;
	}

	printf("eason connect fd=%d,%d,%d,%d",fd,rc,FD_ISSET(fd, &w_set),FD_ISSET(fd, &r_set));
	if (rc == 1 && FD_ISSET(fd, &w_set) && !FD_ISSET(fd, &r_set)) {
		printf("eason connected\n");
		setup_misock_client_ustream();
		return NULL; // connected
	}
	printf("eason connect failed fun=%s,line=%d", __FUNCTION__,__LINE__);

RETURN_1:
	// 10.关闭
	close(fd);
	return NULL;
	
#if 0	
	char send_buf[BUFSIZ];
	char recv_buf[BUFSIZ];
	int maxfd= -1;
	fd_set readfds;
	int ret=-1;
	int i;
	
	while(1) {
		FD_ZERO(&readfds);
 
		FD_SET(0, &readfds);
		maxfd = maxfd > 0 ? maxfd : 0;
		FD_SET(connfd, &readfds);
		maxfd = maxfd > connfd ? maxfd : connfd;
		
		if (0 > select(maxfd + 1, &readfds, NULL, NULL, NULL))
			err_exit("select");
 
		for (i=0; i<=maxfd; i++) 
		{
			if (FD_ISSET(i, &readfds)) 
			{
				if (0 == i) 
				{
					fgets(send_buf, sizeof(send_buf), stdin);		
					if (0 > send(connfd, send_buf, strlen(send_buf) + 1, 0))
						err_exit("send");				
				} 
				else if (connfd == i) 
				{
					if (0 > (ret = recv(connfd, recv_buf, BUFSIZ, 0)))
						err_exit("recv");
					else if (0 == ret) 
					{
						printf("server quit!\n");
						exit(0);
					}
					
					recv_buf[ret] = '\0';
					printf("server: %s\n", recv_buf);
				}
			}
		}
	}
	close(connfd);
	exit(0);
#endif	
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值