MT7628学习笔记(19)——TCP客户端ipk软件包编写与应用
程序员文章站
2024-02-22 10:22:40
...
基础步骤参考:ipk软件包编写与应用
一、编写驱动
src/net_control_client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> //系统函数
#include <string.h>
#include <pthread.h> //多线程库
#include "net_control_client.h"
ts_tcp_client s_tcp_client;
static int connect_to_server(void)
{
while(connect(s_tcp_client.socket_fd, (struct sockaddr *) &(s_tcp_client.server_socket_addr),
sizeof(struct sockaddr)) != 0){
//if connect error reconnect after 5 seconds
perror("connect");
printf("***reconnect after 5s***\n");
sleep(5);
printf("***reconnect...***\n");
}
printf("***connected***\n");
#if 1//test message send
char test_msg[] = "This is from client";
send(s_tcp_client.socket_fd, test_msg ,sizeof(test_msg),0);
#endif
return 0;
}
/*
* 接收socket数据函数.
* client_fd - 客户端连接的socket。
*/
static int receive_packet(int client_fd)
{
unsigned char buf[TCP_BUFFER_SIZE];
int recvbytes;
while(1){
/*接收*/
bzero(buf,sizeof(buf));
recvbytes = recv(client_fd,buf,TCP_BUFFER_SIZE,0);
printf("Receive %d bytes\n",recvbytes);
if (recvbytes <= 0){//receive error or disconnected
perror("recv");
/*reconnect to server*/
// printf("close socket id = %d\n", s_tcp_client.socket_fd);
close(s_tcp_client.socket_fd); //关闭通道
s_tcp_client.socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (s_tcp_client.socket_fd == -1){
perror("socket");
return -1;
}
// printf("new socket id = %d\n", s_tcp_client.socket_fd);
if (connect_to_server() != 0){
printf("###connect_to_server error###\n");
return -1;
}
}else{//receive success
#if 1//test
int i;
printf("***GET:\n");
for (i = 0; i < recvbytes; i++){
printf("0x%02X %c\n", *(buf+i), *(buf+i));
}
#endif
}
}
return 0;
}
/*tcp clinet running function*/
int tcp_client_start(void)
{
printf("***connect to %s.....***\n", s_tcp_client.server_ip);
/*connect to server*/
if (connect_to_server() != 0){
printf("###connect_to_server error###\n");
return -1;
}
receive_packet(s_tcp_client.socket_fd);
return 0;
}
/*
* tcp_client initialize function
* port_num - TCP server port number
* server_ip - TCP server ip
* */
int tcp_client_init(unsigned short port_num, char *server_ip)
{
int res;
struct in_addr test_addr;
/*initialize variable*/
if (port_num > 0){
s_tcp_client.server_port = port_num;
}else{
printf("###invalid tcp server port:%d###\n", port_num);
return -1;
}
if (server_ip == NULL){
printf("###server_ip cannot be NULL###\n");
return -1;
}else{
strcpy(s_tcp_client.server_ip, server_ip);//record ip
}
/*建立socket描述符*/
if ((s_tcp_client.socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket");
return -1;
}
printf("socket id = %d\n", s_tcp_client.socket_fd);
/*
* 填充服务器sockaddr结构
*/
bzero(&(s_tcp_client.server_socket_addr), sizeof(struct sockaddr_in)); //memset
s_tcp_client.server_socket_addr.sin_family = AF_INET;
inet_pton(AF_INET, s_tcp_client.server_ip, &(s_tcp_client.server_socket_addr.sin_addr.s_addr)); //把ip地址转化为用于网络传输的二进制数值
s_tcp_client.server_socket_addr.sin_port = htons(s_tcp_client.server_port); //将主机字节顺序转为网络字节顺序
bzero(&(s_tcp_client.server_socket_addr.sin_zero), 8);
return 0;
}
int main(int argc, char *argv[])
{
int i = 0;
int res;
pthread_t tcp_thread_id;//返回的线程值
char tcp_server_port[256];
char tcp_server_ip[256];
if (argc >= 2){
if (strcmp(argv[1],"-v") == 0){
printf("net_control_client v1.0\n");
return 0;
}else if (strcmp(argv[1],"-h") == 0){
printf("-v for version\n");
printf("-h for help\n");
printf("tcp_connect <IP> <port>\n");
return 0;
}else if (strcmp(argv[1], "tcp_connect") == 0){
/*tcp demo*/
strcpy(tcp_server_ip, argv[2]);
strcpy(tcp_server_port, argv[3]);
/*initialize functions*/
res = tcp_client_init((unsigned short)atoi(tcp_server_port), tcp_server_ip);//set tcp clinet setting
if (res == -1){
printf("###tcp_server_init error###\n");
return -1;
}
//create thread for TCP communication
pthread_create(&tcp_thread_id, NULL, (void *)tcp_client_start, NULL);
}else{
printf("Unknown argument %s\n",argv[1]);
return -1;
}
}
while(1){
if (i < 100){
i++;
}else{
i = 0;
}
sleep(1);
}
exit(0);
}
src/net_control_client.h
#ifndef NET_CONTROL_CLINET_H_
#define NET_CONTROL_CLINET_H_
#include <arpa/inet.h>
#define TCP_BUFFER_SIZE 1024//max buff of receive buffer for tcp
typedef struct{//tcp client class
unsigned short server_port;
char server_ip[64];
int socket_fd;//socket
struct sockaddr_in server_socket_addr;
}ts_tcp_client;
#endif /* NET_CONTROL_CLINET_H_ */
src/Makefile
all:net_control_client
OBJS = net_control_client.o
net_control_client:$(OBJS)
$(CC) $(CFLAGS) -o aaa@qq.com $(OBJS) -lpthread
clean:
rm -f net_control_client *.o
Makefile
include $(TOPDIR)/rules.mk#将openwrt顶层目录下的rules.mk文件中的内容导入进来
PKG_NAME:=net_control_client#软件包名
PKG_VERSION:=1.0#软件包版本
PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)#真正编译当前软件包的目录
include $(INCLUDE_DIR)/package.mk#将$(TOPDIR)/include目录下的package.mk文件中的内容导入进来
define Package/net_control_client
SECTION:=wrtnode#软件包类型
CATEGORY:=WRTnode#menuconfig中软件包所属的一级目录
SUBMENU :=demos#menuconfig中软件包所属的二级目录
TITLE:=net control client -a TCP client#软件包标题
DEPENDS:=+libpthread#运行本软件依赖的其他包
endef
define Package/net_control_client/description #软件包描述
A sample socket net control client
endef
define Build/Prepare #编译之前的准备动作
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Package/net_control_client/install #软件包的安装方法,主要就是将一系列编译好的文件、启动脚本、UCI配置文件等拷贝到指定位置
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/net_control_client $(1)/bin/
endef
$(eval $(call BuildPackage,net_control_client))
二、选中软件包
三、编译软件包
1、进入 OpenWrt 顶层目录,使用以下命令单独编译软件包:
make package/net_control_client/compile V=s
四、软件包发送到开发板并安装:
scp ~/linux/MTK/MT7628/SDK/openwrt-hiwooya/bin/ramips/packages/base/net_control_client_1.0_ramips_24kec.ipk aaa@qq.com:/tmp
opkg install net_control_client_1.0_ramips_24kec.ipk
五、测试运行软件包
1、连接本地服务器测试::
net_control_client tcp_connect 172.16.2.44 7777
2、连接外网服务器测试:
测试服务器地址:http://tcplab.openluat.com/