Master The Pico WiFi: Client Sockets
Written by Harry Fairhead and Mike James   
Tuesday, 18 November 2025
Article Index
Master The Pico WiFi: Client Sockets
Setting Up Sockets
The Complete Program

There are big advantages to using FreeRTOS with the Pico and one of them is being able to use sockets. This is an extract from our latest book on the Raspberry Pi Pico 2W in C.

Master the Raspberry Pi Pico in C:
WiFiwith lwIP, mbedTLS & FreeRTOS
Second Edition

By Harry Fairhead & Mike James

masterPicoE2360

Buy from Amazon.

Contents

       Preface

  1. The Pico WiFi Stack
  2. Introduction To TCP
          Extract:
    Simplest HTTP Client *
  3. More Advanced TCP
  4. SSL/TLS and HTTPS
          Extract:
    Simplest HTTPS Client *
  5. Details of Cryptography
          Extract:
    Random Numbers*
  6. Servers
          Extract: HTTP Server *    
  7. UDP For Speed
          Extract: 
    Basic UDP *
  8. SNTP For Time-Keeping
  9. SMTP For Email
  10. MQTT For The IoT
  11. FreeRTOS
         Extract: 
    Installing FreeRTOS 
  12. Client Sockets
       Extract:
    Client Sockets  NEW!!
  13. Socket Server
  14. Secure Sockets

    Appendix 1 Getting Started In C

* Extracts from the first edition not yet updated.

<ASIN:B0FDYDPQ54> 

Sockets are a general-purpose way of communicating over networks and similar infrastructure. Essentially they are a generalization of files to things other than storage devices. They aren’t part of the C standard, but are available on all POSIX-compliant operating systems such as Linux. As a result there are lots of programs that implement network transactions using sockets. Although the Pico SDK does not support sockets, lwIP does, but it requires support for threads or tasks as implemented by FreeRTOS. The main problem is that lwIP’s sockets are not a 100% implementation of the POSIX standard and you are almost certain to require some changes to any existing program. However, the differences are small enough not to be a burden when creating a new program.

The biggest problem is that neither FreeRTOS nor lwIP sockets are well supported by Raspberry Pi and the documentation is severely lacking. This is what this chapter sets out to remedy.

All sockets do is transport data from one point to another, so you can use them to communicate using almost any standard protocol, like HTTP, or a custom protocol of your own devising. Put simply, a socket is a stream of bytes that you can send over a communication channel.

Socket Basics

The basic steps in using a socket are fairly simple:

  1. Create socket

  2. Connect the socket to an address

  3. Transfer data.

Sockets connect to other sockets by their addresses. The simplest case is where there are just two sockets, or two endpoints, communicating. Once the connection is made, the two sockets at each end of the connection operate in more or less the same way. In general, one of the sockets, the client, will have initiated the connection and the other, the server, will have accepted it.

There is a conceptual difference between a client socket and a server socket. A server socket is set up and then it waits for clients to connect to it. A client socket actively seeks a connection with a server. Once connected, data can flow in both directions and the difference between the two ends of the connection becomes less. That is, the difference between client and server is only about who initiates the connection.

Socket Functions

There are several basic socket functions that are needed for specific purposes and these are common to all sockets implementations including lwIP:

Create a socket

sockfd= socket(int socket_family, int socket_type,
int protocol);

This returns a socket descriptor, an int which you use in other socket functions. The socket_family is where you specify the type of communications link to be use and this is where sockets are most general. There are lots of communications methods that sockets can use, including AF_UNIX or AF_LOCAL, which don't use a network, but allow inter-communication between processes on the same machine. In most cases, you are going to be using AF_INET for IPv4 or AF_INET6 for IPv6 networking.  lwIP supports both but IPv6 is only available if you enable it.

The socket_type specifies the general protocol to be used. In most cases you will use SOCK_STREAM which specifies a reliable two-way connection - for IP communications this means TCP/IP is used. For some applications you might want to use SOCK_DGRAM, which specifies that the data should be sent without confirming that it has been received. This is a broadcast mechanism that corresponds to UDP for IP communications. LwIP supports both and also SOCK_RAW.

The protocol parameter selects a sub-protocol of the socket type. In most cases you can simply set it to 0 or IPPROTO_IP.  LwIP supports IPPROTO_ICMP, IPPROTO_IP, IPPROTO_IP and IPPROTO_IP

As we are going to be working with sockets that basically work with the web, we will use AF_INET and SOCK_STREAM. 

Connect a socket to an address

To connect a socket as a client of another use the connect function: 

int connect(int sockfd,const struct sockaddr *addr,
                                      socklen_t addrlen);

The sockfd parameter is just the socket file descriptor returned from the socket function. The addr parameter points at a sockaddr struct which contains the address of the socket you want to connect to. Of course, addrlen just specifies the size of the struct. The socket address type depends on the underlying communications medium that the socket uses, but in most cases it is just an IP address.

Reading and Writing

As an open socket is just a file, you can use the standard read and write functions that you would use to work with a file. There are two additional functions, send and recv, which work in the same way as write and read but have an additional final parameter that can be used to control exactly how the transaction is performed. It is worth noting that Windows sockets do not support read and write but they do work with recv and send and if you are developing a cross-platform or porting a Windows socket program then it might be easier to use these alternatives.

Both read and write are blocking in the sense that they do not return until there is either data to process or the data has been sent. This makes writing programs easier but without the use of threads or events brings the rest of the program to a halt. You can convert read and write into non-blocking operations but this is less commonly used.



Last Updated ( Tuesday, 18 November 2025 )