MiCO 提供 socket 相关 API 包括 3 种,分别是:TCP/UDP, TCP TLS/SLL,和 TCPIP 通信。 更详细的 API 参数及返回值说明,可参考: doxygen 文档,更多示例代码查看可至 MiCO Demos。
本例实现:创建一个 TCP Client 客户端,配网成功后,主动连接指定的TCP Server服务器,当 Server 发来字符串数据时,client 将回传数据给 TCP Server。
#include "mico.h"
#include "SocketUtils.h"
#define tcp_client_log(M, ...) custom_log("TCP", M, ##__VA_ARGS__)
static char tcp_remote_ip[16] = "192.168.3.53"; /*remote ip address*/
static int tcp_remote_port = 6000; /*remote port*/
static mico_semaphore_t wait_sem = NULL;
static void micoNotify_WifiStatusHandler( WiFiEvent status, void* const inContext )
{
switch ( status )
{
case NOTIFY_STATION_UP:
mico_rtos_set_semaphore( &wait_sem );
break;
case NOTIFY_STATION_DOWN:
case NOTIFY_AP_UP:
case NOTIFY_AP_DOWN:
break;
}
}
/*when client connected wlan success,create socket*/
void tcp_client_thread( mico_thread_arg_t arg )
{
UNUSED_PARAMETER( arg );
OSStatus err;
struct sockaddr_in addr;
struct timeval t;
fd_set readfds;
int tcp_fd = -1, len;
char *buf = NULL;
buf = (char*) malloc( 1024 );
require_action( buf, exit, err = kNoMemoryErr );
tcp_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
require_action( IsValidSocket( tcp_fd ), exit, err = kNoResourcesErr );
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr( tcp_remote_ip );
addr.sin_port = htons(tcp_remote_port);
tcp_client_log( "Connecting to server: ip=%s port=%d!", tcp_remote_ip,tcp_remote_port );
err = connect( tcp_fd, (struct sockaddr *)&addr, sizeof(addr) );
require_noerr( err, exit );
tcp_client_log( "Connect success!" );
t.tv_sec = 2;
t.tv_usec = 0;
while ( 1 )
{
FD_ZERO( &readfds );
FD_SET( tcp_fd, &readfds );
require_action( select( tcp_fd + 1, &readfds, NULL, NULL, &t) >= 0, exit,
err = kConnectionErr );
/* recv wlan data, and send back */
if ( FD_ISSET( tcp_fd, &readfds ) )
{
len = recv( tcp_fd, buf, 1024, 0 );
require_action( len >= 0, exit, err = kConnectionErr );
if ( len == 0 )
{
tcp_client_log( "TCP Client is disconnected, fd: %d", tcp_fd );
goto exit;
}
tcp_client_log("Client fd: %d, recv data %d", tcp_fd, len);
len = send( tcp_fd, buf, len, 0 );
tcp_client_log("Client fd: %d, send data %d", tcp_fd, len);
}
}
exit:
if ( err != kNoErr ) tcp_client_log( "TCP client thread exit with err: %d", err );
if ( buf != NULL ) free( buf );
SocketClose( &tcp_fd );
mico_rtos_delete_thread( NULL );
}
int application_start( void )
{
OSStatus err = kNoErr;
mico_rtos_init_semaphore( &wait_sem, 1 );
/*Register user function for MiCO nitification: WiFi status changed */
err = mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED,
(void *) micoNotify_WifiStatusHandler, NULL );
require_noerr( err, exit );
/* Start MiCO system functions according to mico_config.h */
err = mico_system_init( mico_system_context_init( 0 ) );
require_noerr( err, exit );
/* Wait for wlan connection*/
mico_rtos_get_semaphore( &wait_sem, MICO_WAIT_FOREVER );
tcp_client_log( "wifi connected successful" );
/* Start TCP client thread */
err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "TCP_client", tcp_client_thread, 0x800, 0 );
require_noerr_string( err, exit, "ERROR: Unable to start the tcp client thread." );
exit:
if ( wait_sem != NULL )
mico_rtos_deinit_semaphore( &wait_sem );
mico_rtos_delete_thread( NULL );
return err;
}
本例实现:创建一个 TCP server,等待TCP client的连接,当 client 向该 server 发送字符时,TCP server将接收到的字符回传给TCP client。
#include "mico.h"
#include "SocketUtils.h"
#define tcp_server_log(M, ...) custom_log("TCP", M, ##__VA_ARGS__)
#define SERVER_PORT 20000 /*set up a tcp server,port at 20000*/
void micoNotify_WifiStatusHandler( WiFiEvent event, void* const inContext )
{
IPStatusTypedef para;
switch ( event )
{
case NOTIFY_STATION_UP:
micoWlanGetIPStatus( ¶, Station );
tcp_server_log("Server established at ip: %s port: %d",para.ip, SERVER_PORT);
break;
case NOTIFY_STATION_DOWN:
case NOTIFY_AP_UP:
case NOTIFY_AP_DOWN:
break;
}
}
void tcp_client_thread( mico_thread_arg_t arg )
{
OSStatus err = kNoErr;
int fd = (int) arg;
int len = 0;
fd_set readfds;
char *buf = NULL;
struct timeval t;
buf = (char*) malloc( 1024 );
require_action( buf, exit, err = kNoMemoryErr );
t.tv_sec = 5;
t.tv_usec = 0;
while ( 1 )
{
FD_ZERO( &readfds );
FD_SET( fd, &readfds );
require_action( select( fd+1, &readfds, NULL, NULL, &t) >= 0, exit, err = kConnectionErr );
if ( FD_ISSET( fd, &readfds ) ) /*one client has data*/
{
len = recv( fd, buf, 1024, 0 );
require_action( len >= 0, exit, err = kConnectionErr );
if ( len == 0 )
{
tcp_server_log( "TCP Client is disconnected, fd: %d", fd );
goto exit;
}
tcp_server_log("fd: %d, recv data %d from client", fd, len);
len = send( fd, buf, len, 0 );
tcp_server_log("fd: %d, send data %d to client", fd, len);
}
}
exit:
if ( err != kNoErr ) tcp_server_log( "TCP client thread exit with err: %d", err );
if ( buf != NULL ) free( buf );
SocketClose( &fd );
mico_rtos_delete_thread( NULL );
}
/* TCP server listener thread */
void tcp_server_thread( mico_thread_arg_t arg )
{
UNUSED_PARAMETER( arg );
OSStatus err = kNoErr;
struct sockaddr_in server_addr, client_addr;
socklen_t sockaddr_t_size = sizeof(client_addr);
char client_ip_str[16];
int tcp_listen_fd = -1, client_fd = -1;
fd_set readfds;
tcp_listen_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
require_action( IsValidSocket( tcp_listen_fd ), exit, err = kNoResourcesErr );
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;/* Accept conenction request on all network interface */
server_addr.sin_port = htons( SERVER_PORT );/* Server listen on port: 20000 */
err = bind( tcp_listen_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) );
require_noerr( err, exit );
err = listen( tcp_listen_fd, 0 );
require_noerr( err, exit );
while ( 1 )
{
FD_ZERO( &readfds );
FD_SET( tcp_listen_fd, &readfds );
require( select( tcp_listen_fd + 1, &readfds, NULL, NULL, NULL) >= 0, exit );
if ( FD_ISSET( tcp_listen_fd, &readfds ) )
{
client_fd = accept( tcp_listen_fd, (struct sockaddr *) &client_addr, &sockaddr_t_size );
if ( IsValidSocket( client_fd ) )
{
// inet_ntoa( client_ip_str, client_addr.s_ip );
strcpy( client_ip_str, inet_ntoa( client_addr.sin_addr ) );
tcp_server_log( "TCP Client %s:%d connected, fd: %d", client_ip_str, client_addr.sin_port, client_fd );
if ( kNoErr
!= mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "TCP Clients",
tcp_client_thread,
0x800, client_fd ) )
SocketClose( &client_fd );
}
}
}
exit:
if ( err != kNoErr ) tcp_server_log( "Server listerner thread exit with err: %d", err );
SocketClose( &tcp_listen_fd );
mico_rtos_delete_thread( NULL );
}
int application_start( void )
{
OSStatus err = kNoErr;
/*Register user function for MiCO nitification: WiFi status changed */
err = mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED,
(void *) micoNotify_WifiStatusHandler,
NULL );
require_noerr( err, exit );
/* Start MiCO system functions according to mico_config.h */
err = mico_system_init( mico_system_context_init( 0 ) );
require_noerr( err, exit );
/* Start TCP server listener thread*/
err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "TCP_server", tcp_server_thread,
0x800,
0 );
require_noerr_string( err, exit, "ERROR: Unable to start the tcp server thread." );
exit:
mico_rtos_delete_thread( NULL );
return err;
}
本例实现:启动 UDP 广播服务,与同一网关下的不同 IP 地址的主机的同一端口号进行通讯。
#include "mico.h"
#define udp_broadcast_log(M, ...) custom_log("UDP", M, ##__VA_ARGS__)
#define LOCAL_UDP_PORT 20000
#define REMOTE_UDP_PORT 20001
char* data = "UDP broadcast data";
/*create udp socket*/
void udp_broadcast_thread( mico_thread_arg_t arg )
{
UNUSED_PARAMETER( arg );
OSStatus err;
struct sockaddr_in addr;
int udp_fd = -1;
/*Establish a UDP port to receive any data sent to this port*/
udp_fd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
require_action( IsValidSocket( udp_fd ), exit, err = kNoResourcesErr );
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons( LOCAL_UDP_PORT );
err = bind( udp_fd, (struct sockaddr *) &addr, sizeof(addr) );
require_noerr( err, exit );
udp_broadcast_log("Start UDP broadcast mode, local port: %d, remote port: %d", LOCAL_UDP_PORT, REMOTE_UDP_PORT);
while ( 1 )
{
udp_broadcast_log( "broadcast now!" );
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_BROADCAST;
addr.sin_port = htons( REMOTE_UDP_PORT );
/*the receiver should bind at port=20000*/
sendto( udp_fd, data, strlen( data ), 0, (struct sockaddr *) &addr, sizeof(addr) );
mico_thread_sleep( 2 );
}
exit:
if ( err != kNoErr )
udp_broadcast_log("UDP thread exit with err: %d", err);
mico_rtos_delete_thread( NULL );
}
int application_start( void )
{
OSStatus err = kNoErr;
/* Start MiCO system functions according to mico_config.h */
err = mico_system_init( mico_system_context_init( 0 ) );
require_noerr( err, exit );
err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "udp_broadcast", udp_broadcast_thread, 0x800, 0 );
require_noerr_string( err, exit, "ERROR: Unable to start the UDP thread." );
exit:
if ( err != kNoErr )
udp_broadcast_log("Thread exit with err: %d", err);
mico_rtos_delete_thread( NULL );
return err;
}
本示例实现:启动 udp 单播服务,与指定 IP 地址 的主机端口号进行数据通信。
#include "mico.h"
#define udp_unicast_log(M, ...) custom_log("UDP", M, ##__VA_ARGS__)
#define LOCAL_UDP_PORT 20000
void micoNotify_WifiStatusHandler( WiFiEvent event, void* const inContext )
{
IPStatusTypedef para;
switch ( event )
{
case NOTIFY_STATION_UP:
micoWlanGetIPStatus( ¶, Station );
udp_unicast_log( "Wlan connected, Local ip address: %s", para.ip );
break;
case NOTIFY_STATION_DOWN:
case NOTIFY_AP_UP:
case NOTIFY_AP_DOWN:
break;
}
}
/*create udp socket*/
void udp_unicast_thread( void *arg )
{
UNUSED_PARAMETER( arg );
OSStatus err;
struct sockaddr_in addr;
fd_set readfds;
socklen_t addrLen = sizeof(addr);
int udp_fd = -1, len;
char ip_address[16];
uint8_t *buf = NULL;
buf = malloc( 1024 );
require_action( buf, exit, err = kNoMemoryErr );
/*Establish a UDP port to receive any data sent to this port*/
udp_fd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
require_action( IsValidSocket( udp_fd ), exit, err = kNoResourcesErr );
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = htons(LOCAL_UDP_PORT);
err = bind( udp_fd, (struct sockaddr *)&addr, sizeof(addr) );
require_noerr( err, exit );
udp_unicast_log("Open local UDP port %d", LOCAL_UDP_PORT);
while ( 1 )
{
FD_ZERO( &readfds );
FD_SET( udp_fd, &readfds );
require_action( select(udp_fd + 1, &readfds, NULL, NULL, NULL) >= 0, exit,
err = kConnectionErr );
/*Read data from udp and send data back */
if ( FD_ISSET( udp_fd, &readfds ) )
{
len = recvfrom( udp_fd, buf, 1024, 0, (struct sockaddr *)&addr, &addrLen );
require_action( len >= 0, exit, err = kConnectionErr );
strcpy(ip_address, inet_ntoa(addr.sin_addr));
udp_unicast_log( "udp recv from %s:%d, len:%d", ip_address,addr.sin_port, len );
sendto( udp_fd, buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in) );
}
}
exit:
if ( err != kNoErr )
udp_unicast_log("UDP thread exit with err: %d", err);
if ( buf != NULL ) free( buf );
mico_rtos_delete_thread( NULL );
}
int application_start( void )
{
OSStatus err = kNoErr;
/*Register user function for MiCO nitification: WiFi status changed */
err = mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED,
(void *) micoNotify_WifiStatusHandler, NULL );
require_noerr( err, exit );
/* Start MiCO system functions according to mico_config.h */
err = mico_system_init( mico_system_context_init( 0 ) );
require_noerr( err, exit );
err = mico_rtos_create_thread( NULL, MICO_APPLICATION_PRIORITY, "udp_unicast",
(mico_thread_function_t)udp_unicast_thread, 0x800, 0 );
require_noerr_string( err, exit, "ERROR: Unable to start the UDP thread." );
exit:
if ( err != kNoErr )
udp_unicast_log("Thread exit with err: %d", err);
mico_rtos_delete_thread( NULL );
return err;
}
上一篇:4.2 Http 通信
下一篇:3.4 设置Wi-Fi网络参数
版权所有 © 2017 - 2018 MXCHIP授权代理商 - 深圳市博易特智能科技有限公司 粤ICP备17063559号
服务热线:0755-23733662 Email:info@mxchip.cc