MXOS Socket APIs
mxos provides three socket-related APIs: TCP/UDP, TCP TLS/SLL, and TCP/IP communication.
⊕ mxos-demos SDK를 참조한다.
1. TCP/UDP communication
TCP/UDP Comm. API | Description |
socket | Create a communication terminal |
setsockopt | Set socket option |
getsockopt | Get socket option |
bind | Bind a name to the socket |
connect | Initialize a socket connection |
listen | Listening for a socket connection |
accept | Accept a socket connection |
select | Monitor multiple file descriptors |
send | Send a message on a socket |
write | Send a message on the socket |
sendto | Send a message from the socket to the destination address |
recv | Receive a message from a socket |
read | Read a message from a socket |
recvfrom | Receive a message from a socket and get the source address |
close | Close a file descriptor |
inet_addr | Convert network host addresses, from IPv4 numbers and dot symbols, to network byte order binary data |
inet_ntoa | Convert the network host address to an IPv4 dotted decimal string according to the network byte order |
2. TCP TLS/SSL communication
TCP TLS/SSL Comm. API | Descriptiontion |
ssl_set_cert | Create a certificate and private key for an SSL server by being used by the SSL server |
ssl_connect | SSL client creates an SSL connection |
ssl_accept | SSL server accepts an SSL connection |
ssl_send | SSL sending data |
ssl_recv | SSL receiving data |
ssl_close | Turn off SSL and release resources |
3. TCP/IP communication
TCP/IP Comm. API | Description |
gethostbyname | Obtain an IP address from the host name |
set_tcp_keepalive | Set the TCP keep-alive mechanism parameters |
get_tcp_keepalive | Get TCP keep-alive mechanism parameters |
4. Example
tcp_client.c
In this example, a TCP Client client is created.
After the network is successfully deployed, the specified TCP server is actively connected.
When the server sends string data, the client will return data to the TCP server.
#include "mxos.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 mxos_semaphore_t wait_sem = NULL;
static void mxosNotify_WifiStatusHandler( WiFiEvent status, void* const inContext )
{
switch ( status )
{
case NOTIFY_STATION_UP:
mxos_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( mxos_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 );
mxos_rtos_delete_thread( NULL );
}
int application_start( void )
{
OSStatus err = kNoErr;
mxos_rtos_init_semaphore( &wait_sem, 1 );
/*Register user function for mxos nitification: WiFi status changed */
err = mxos_system_notify_register( mxos_notify_WIFI_STATUS_CHANGED,
(void *) mxosNotify_WifiStatusHandler, NULL );
require_noerr( err, exit );
/* Start mxos system functions according to mxos_config.h */
err = mxos_system_init( mxos_system_context_init( 0 ) );
require_noerr( err, exit );
/* Wait for wlan connection*/
mxos_rtos_get_semaphore( &wait_sem, mxos_WAIT_FOREVER );
tcp_client_log( "wifi connected successful" );
/* Start TCP client thread */
err = mxos_rtos_create_thread( NULL, mxos_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 )
mxos_rtos_deinit_semaphore( &wait_sem );
mxos_rtos_delete_thread( NULL );
return err;
}
tcp_server.c
In this example, a TCP server is created to wait for a TCP client connection.
When the client sends a character to the server, the TCP server returns the received character to the TCP client.
#include "mxos.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 mxosNotify_WifiStatusHandler( WiFiEvent event, void* const inContext )
{
IPStatusTypedef para;
switch ( event )
{
case NOTIFY_STATION_UP:
mxosWlanGetIPStatus( ¶, 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( mxos_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 );
mxos_rtos_delete_thread( NULL );
}
/* TCP server listener thread */
void tcp_server_thread( mxos_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
!= mxos_rtos_create_thread( NULL, mxos_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 );
mxos_rtos_delete_thread( NULL );
}
int application_start( void )
{
OSStatus err = kNoErr;
/*Register user function for mxos nitification: WiFi status changed */
err = mxos_system_notify_register( mxos_notify_WIFI_STATUS_CHANGED,
(void *) mxosNotify_WifiStatusHandler,
NULL );
require_noerr( err, exit );
/* Start mxos system functions according to mxos_config.h */
err = mxos_system_init( mxos_system_context_init( 0 ) );
require_noerr( err, exit );
/* Start TCP server listener thread*/
err = mxos_rtos_create_thread( NULL, mxos_APPLICATION_PRIORITY, "TCP_server", tcp_server_thread,
0x800,
0 );
require_noerr_string( err, exit, "ERROR: Unable to start the tcp server thread." );
exit:
mxos_rtos_delete_thread( NULL );
return err;
}
udp_broadcast.c
This example is implemented by starting the UDP broadcast service
and communicating with the same port number of the host with a different IP address under the same gateway.
#include "mxos.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( mxos_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) );
mxos_thread_sleep( 2 );
}
exit:
if ( err != kNoErr )
udp_broadcast_log("UDP thread exit with err: %d", err);
mxos_rtos_delete_thread( NULL );
}
int application_start( void )
{
OSStatus err = kNoErr;
/* Start mxos system functions according to mxos_config.h */
err = mxos_system_init( mxos_system_context_init( 0 ) );
require_noerr( err, exit );
err = mxos_rtos_create_thread( NULL, mxos_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);
mxos_rtos_delete_thread( NULL );
return err;
}
udp_unicast.c
This example implementation starts the udp unicast service and communicates data with the host port number of the specified IP address.
#include "mxos.h"
#define udp_unicast_log(M, ...) custom_log("UDP", M, ##__VA_ARGS__)
#define LOCAL_UDP_PORT 20000
void mxosNotify_WifiStatusHandler( WiFiEvent event, void* const inContext )
{
IPStatusTypedef para;
switch ( event )
{
case NOTIFY_STATION_UP:
mxosWlanGetIPStatus( ¶, 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 );
mxos_rtos_delete_thread( NULL );
}
int application_start( void )
{
OSStatus err = kNoErr;
/*Register user function for mxos nitification: WiFi status changed */
err = mxos_system_notify_register( mxos_notify_WIFI_STATUS_CHANGED,
(void *) mxosNotify_WifiStatusHandler, NULL );
require_noerr( err, exit );
/* Start mxos system functions according to mxos_config.h */
err = mxos_system_init( mxos_system_context_init( 0 ) );
require_noerr( err, exit );
err = mxos_rtos_create_thread( NULL, mxos_APPLICATION_PRIORITY, "udp_unicast",
(mxos_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);
mxos_rtos_delete_thread( NULL );
return err;
}
이상 끝 ~~~