Openwrt ubox应用例子: 实现C/S网络通信
程序员文章站
2022-06-09 18:02:45
...
ubox是Openwrt的一个帮助工具包, 包含了MD5,链表,平衡树,blob标签式二进制数据包的生成和解释......等等基础API, 以及uloop,usock,ustream,ulog等应用。 通过学习ubox可以更好地理解和融入Openwrt框架体系。
通过应用其中的uloop和usock可实现基于文件句柄监控和事件驱动机制的C/S结构网络通信应用。
以下是一个实现的小例子:
1. 服务端 usock_server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <libubox/usock.h>
#include <libubox/uloop.h>
static char *host_addr="192.168.1.9";
static char *server_port="5678";
static char *strhello="Welcome to UBOX world!\n";
static char *strreply="Add client to uloop_fd_event successfully!\n";
/* client fd event call_back */
void sevent_cb(struct uloop_fd *fd, unsigned int events)
{
char buf[1024];
struct timeval tm;
int ret;
gettimeofday(&tm,NULL);
if(events & ULOOP_READ) {
printf("%ld: ULOOP_READ is triggered! sock fd=%d, events=%d\n", tm.tv_sec,fd->fd, events);
ret=read(fd->fd, buf, sizeof(buf));
buf[ret]=0;
printf("Client MSG: %s \n", buf);
if(events & ULOOP_WRITE) {
write(fd->fd, strhello, strlen(strhello));
}
}
}
/* server fd event call_back function */
void server_cb(struct uloop_fd *fd, unsigned int events)
{
printf("server_cb is triggered! events=%d\n",events);
int client_fd=accept(fd->fd, NULL,0);
if(client_fd<0) {
perror("server_cb accept");
return;
}
printf(" >>>>>>> New client accepted! >>>>>>\n");
write(client_fd,strhello,strlen(strhello));
struct uloop_fd *ucli_fd=calloc(1,sizeof(struct uloop_fd));
if(ucli_fd==NULL)
return;
/* add client fd to uloop event */
ucli_fd->fd= client_fd;
ucli_fd->cb = sevent_cb;
printf("Add client to uloop_fd...\n");
uloop_fd_add(ucli_fd, ULOOP_READ | ULOOP_WRITE | ULOOP_EDGE_TRIGGER);
}
struct uloop_fd server_fd = {
.cb = server_cb,
};
void main(void)
{
int sfd;
char buf[1024];
/* 1. init uloop */
uloop_init();
/* 2. create server usock */
sfd=usock(USOCK_TCP|USOCK_SERVER, host_addr, server_port);
if(sfd<0) {
perror("usock");
exit(-1);
}
printf("Succeed to create server at %s:%s\n",host_addr, server_port);
/* 3. add server fd to uloop event */
server_fd.fd=sfd;
uloop_fd_add(&server_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER); /* read only */
/* 4. loop events monitoring */
uloop_run();
/* 5. end uloop */
uloop_done();
}
2. 客户端 usock_client.c
#include <stdio.h>
#include <stdlib.h>
#include <libubox/usock.h>
#include <libubox/uloop.h>
#include <string.h>
#include <sys/time.h>
char *host_addr="192.168.1.9";
char *server_port="5678";
char *strhello="Hello UBOX!";
void cevent_cb(struct uloop_fd *fd, unsigned int events)
{
char buf[1024];
struct timeval tm;
gettimeofday(&tm,NULL);
if(events & ULOOP_READ) {
printf("%ld: event ULOOP_READ is triggered! sock fd=%d, events=%d\n",tm.tv_sec, fd->fd, events);
read(fd->fd, buf, sizeof(buf));
printf("MSG from server: %s \n", buf);
if(events & ULOOP_WRITE) {
write(fd->fd, strhello, strlen(strhello));
}
sleep(1);
}
}
struct uloop_fd client_fd =
{
.cb = cevent_cb,
};
void main(void)
{
int cfd;
char buf[1024];
int ret;
uloop_init();
cfd=usock(USOCK_TCP, host_addr, server_port);
if(cfd<0) {
perror("usock");
exit(-1);
}
printf("Connect to server %s:%s successfuly!\n", host_addr, server_port);
ret=read(cfd, buf, sizeof(buf));
buf[ret]=0;
printf("receive msg: %s\n",buf);
/* send a msg to trigger ping_pong events */
write(cfd, strhello, strlen(strhello));
client_fd.fd=cfd;
uloop_fd_add(&client_fd, ULOOP_READ | ULOOP_WRITE );
printf("start uloop_run() ...\n");
uloop_run();
uloop_done();
}
3. 本例子在openwrt widora环境下编译通过, Makefile 如下:
export STAGING_DIR=/home/midas-zhou/openwrt_widora/staging_dir
COMMON_USRDIR=/home/midas-zhou/openwrt_widora/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/
CC= $(STAGING_DIR)/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-gcc
CFLAGS += -I$(COMMON_USRDIR)/include
LDFLAGS += -L$(COMMON_USRDIR)/lib
LIBS += -lubox
all: usock_server usock_client test_timeout
usock_server: usock_server.c
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) usock_server.c -o usock_server
usock_client: usock_client.c
$(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) usock_client.c -o usock_client
clean:
rm -rf *.o usock_server usock_client
4. 在openwrt中试验, 首先运行usock_server, 然后启动若干个usock_client, 观察实际效果。
5. 备注: 程序中host_addr 和 Makefile环境变量请根据自己实际情况修改。