Stream Socket (TCP)
The figure below uses the Micrium proprietary socket API function calls. A similar example could be written using the BSD socket API.
Typically, after a TCP server starts, TCP clients can connect and send requests to the server. A TCP server waits until client connections arrive and then creates a dedicated TCP socket connection to process the client’s requests and reply back to the client (if necessary). This continues until either the client or the server closes the dedicated client-server connection. Also while handling multiple, simultaneous client-server connections, the TCP server can wait for new client-server connections
Stream Server (TCP Server)
This example presents a very basic client-server application over a TCP connection. The server presented is simply waits for a connection and send the string ‘Hello World!’
. See TCPIP API Reference Core for a list of all µC/TCP-IP socket API functions.
#define TCP_SERVER_PORT 10000 #define TCP_SERVER_CONN_Q_SIZE 1 #define TCP_SERVER_TX_STR "Hello World!" CPU_BOOLEAN TestTCPServer (void) { NET_SOCK_ID sock_listen; NET_SOCK_ID sock_req; NET_SOCK_ADDR_IP server_sock_addr_ip; NET_SOCK_ADDR_LEN server_sock_addr_ip_size; NET_SOCK_ADDR_IP client_sock_addr_ip; NET_SOCK_ADDR_LEN client_sock_addr_ip_size; CPU_BOOLEAN attempt_conn; CPU_CHAR *pbuf; CPU_INT16S buf_len; NET_SOCK_RTN_CODE tx_size; NET_ERR err; pbuf = TCP_SERVER_TX_STR; buf_len = Str_Len(TCP_SERVER_TX_STR); sock_listen = NetSock_Open( NET_SOCK_ADDR_FAMILY_IP_V4, (1) NET_SOCK_TYPE_STREAM, NET_SOCK_PROTOCOL_TCP, &err); if (err != NET_SOCK_ERR_NONE) { return (DEF_FALSE); } server_sock_addr_ip_size = sizeof(server_sock_addr_ip); (2) Mem_Clr((void *)&server_sock_addr_ip, (CPU_SIZE_T) server_sock_addr_ip_size); server_sock_addr_ip.AddrFamily = NET_SOCK_ADDR_FAMILY_IP_V4; server_sock_addr_ip.Addr = NET_UTIL_HOST_TO_NET_32(NET_SOCK_ADDR_IP_WILD_CARD); server_sock_addr_ip.Port = NET_UTIL_HOST_TO_NET_16(TCP_SERVER_PORT); NetSock_Bind((NET_SOCK_ID ) sock_listen, (3) (NET_SOCK_ADDR *)&server_sock_addr_ip, (NET_SOCK_ADDR_LEN) NET_SOCK_ADDR_SIZE, (NET_ERR *)&err); if (err != NET_SOCK_ERR_NONE) { NetSock_Close(sock_listen, &err); return (DEF_FALSE); } NetSock_Listen( sock_listen, (4) TCP_SERVER_CONN_Q_SIZE, &err); if (err != NET_SOCK_ERR_NONE) { NetSock_Close(sock_listen, &err); return (DEF_FALSE); } do { client_sock_addr_ip_size = sizeof(client_sock_addr_ip); sock_req = NetSock_Accept((NET_SOCK_ID ) sock_listen, (5) (NET_SOCK_ADDR *)&client_sock_addr_ip, (NET_SOCK_ADDR_LEN *)&client_sock_addr_ip_size, (NET_ERR *)&err); switch (err) { case NET_SOCK_ERR_NONE: attempt_conn = DEF_NO; break; case NET_ERR_INIT_INCOMPLETE: case NET_SOCK_ERR_NULL_PTR: case NET_SOCK_ERR_NONE_AVAIL: case NET_SOCK_ERR_CONN_ACCEPT_Q_NONE_AVAIL: case NET_SOCK_ERR_CONN_SIGNAL_TIMEOUT: case NET_OS_ERR_LOCK: attempt_conn = DEF_YES; break; default: attempt_conn = DEF_NO; break; } } while (attempt_conn == DEF_YES); if (err != NET_SOCK_ERR_NONE) { NetSock_Close(sock_req, &err); return (DEF_FALSE); } tx_size = NetSock_TxData( sock_req, (6) pbuf, buf_len, NET_SOCK_FLAG_NONE, &err); NetSock_Close(sock_req, &err); (7) NetSock_Close(sock_listen, &err); return (DEF_TRUE); }
- Open a stream socket (TCP protocol).
- Populate the
NET_SOCK_ADDR_IP
structure for the server address and port, and convert it to network order. - Bind the newly created socket to the address and port specified by
server_sock_addr_ip
. - Set the socket to listen for a connection request coming on the specified port.
- Accept the incoming connection request, and return a new socket for this particular connection. Note that this function call is being called from inside a loop because it might timeout (no client attempts to connect to the server).
- One the connection has been established between the server and a client, transmit the message. Note that the return value of this function is not used here, but a real application should make sure all the message has been sent by comparing that value with the length of the message.
- Close both listen and request sockets. When the server need to stay active, the listen socket stays open so that I can accept additional connection requests. Usually, the server will wait for a connection,
accept()
it, andOSTaskCreate()
a task to handle it.
Stream Client (TCP Client)
The client of the listing below connects to the specified server and receives the string the server sends.
#define TCP_SERVER_IP_ADDR "192.168.1.101" #define TCP_SERVER_PORT 10000 #define RX_BUF_SIZE 15 CPU_BOOLEAN TestTCPClient (void) { NET_SOCK_ID sock; NET_IP_ADDR server_ip_addr; NET_SOCK_ADDR_IP server_sock_addr_ip; NET_SOCK_ADDR_LEN server_sock_addr_ip_size; NET_SOCK_RTN_CODE conn_rtn_code; NET_SOCK_RTN_CODE rx_size; CPU_CHAR rx_buf[RX_BUF_SIZE]; NET_ERR err; sock = NetSock_Open( NET_SOCK_ADDR_FAMILY_IP_V4, (1) NET_SOCK_TYPE_STREAM, NET_SOCK_PROTOCOL_TCP, &err); if (err != NET_SOCK_ERR_NONE) { return (DEF_FALSE); } server_ip_addr = NetASCII_Str_to_IP(TCP_SERVER_IP_ADDR, &err); (2) if (err != NET_ASCII_ERR_NONE) { NetSock_Close(sock, &err); return (DEF_FALSE); } server_sock_addr_ip_size = sizeof(server_sock_addr_ip); (3) Mem_Clr((void *)&server_sock_addr_ip, (CPU_SIZE_T) server_sock_addr_ip_size); server_sock_addr_ip.AddrFamily = NET_SOCK_ADDR_FAMILY_IP_V4; server_sock_addr_ip.Addr = NET_UTIL_HOST_TO_NET_32(server_ip_addr); server_sock_addr_ip.Port = NET_UTIL_HOST_TO_NET_16(TCP_SERVER_PORT); conn_rtn_code = NetSock_Conn((NET_SOCK_ID ) sock, (4) (NET_SOCK_ADDR *)&server_sock_addr_ip, (NET_SOCK_ADDR_LEN) sizeof(server_sock_addr_ip), (NET_ERR *)&err); if (err != NET_SOCK_ERR_NONE) { NetSock_Close(sock, &err); return (DEF_FALSE); } rx_size = NetSock_RxData( sock, (5) rx_buf, RX_BUF_SIZE, NET_SOCK_FLAG_NONE, &err); if (err != NET_SOCK_ERR_NONE) { NetSock_Close(sock, &err); return (DEF_FALSE); } NetSock_Close(sock, &err); (6) return (DEF_TRUE); }
- Open a stream socket (TCP protocol).
- Convert an IPv4 address from ASCII dotted-decimal notation to a network protocol IPv4 address in host-order.
- Populate the
NET_SOCK_ADDR_IP
structure for the server address and port, and convert it to network order. - Connect the socket to a remote host.
- Receive data from the connected socket. Note that the return value for this function is not used here.However, a real application should make sure everything has been received.
- Close the socket.
TCP Connection Configuration
µC/TCP-IP provides a set of APIs to configure TCP connections on an individual basis. These APIs are listed below and detailed in TCP Functions: