Skip to main content

Socket APIs

Spectranext provides comprehensive socket APIs for network programming, supporting both TCP and UDP protocols. You can use these APIs from assembly language or C programs.

Overview

The socket API follows BSD-style socket programming patterns, making it familiar to developers experienced with Unix/Linux networking. The API supports:

  • TCP Sockets: Reliable, connection-oriented communication
  • UDP Sockets: Fast, connectionless datagram communication
  • Socket Polling: Check socket status without blocking
  • Hostname Resolution: DNS lookup for hostnames

Socket Types

TCP Sockets (SOCK_STREAM)

TCP sockets provide reliable, ordered, connection-oriented communication:

  • Reliable: Data is guaranteed to arrive
  • Ordered: Data arrives in the order sent
  • Connection-oriented: Requires connection establishment
  • Use for: HTTP, FTP, Telnet, custom protocols requiring reliability

UDP Sockets (SOCK_DGRAM)

UDP sockets provide fast, connectionless datagram communication:

  • Fast: Lower overhead than TCP
  • Connectionless: No connection required
  • Unreliable: Packets may be lost or arrive out of order
  • Use for: DNS queries, game protocols, real-time data

ROM Routines

Spectranext provides ROM routines for socket operations. These are accessed via call tables when the cartridge is paged in.

Socket Management

SOCKET      equ 0x3E00    ; Allocate a socket
CLOSE equ 0x3E03 ; Close a socket

SOCKET: Allocates a new socket

  • Input: Domain (AF_INET = 0), Type (SOCK_STREAM = 1 or SOCK_DGRAM = 2), Protocol (0)
  • Output: Socket file descriptor in HL (carry clear) or error (carry set)

CLOSE: Closes a socket

  • Input: Socket file descriptor in HL
  • Output: Success (carry clear) or error (carry set)

TCP Operations

LISTEN      equ 0x3E06    ; Listen for incoming connections
ACCEPT equ 0x3E09 ; Accept an incoming connection
CONNECT equ 0x3E0F ; Connect to a remote host

LISTEN: Start listening for connections

  • Input: Socket fd in HL, Backlog in BC
  • Output: Success or error

ACCEPT: Accept an incoming connection

  • Input: Socket fd in HL, sockaddr_in pointer in DE
  • Output: New socket fd in HL or error

CONNECT: Connect to a remote host

  • Input: Socket fd in HL, sockaddr_in pointer in DE
  • Output: Success or error

Data Transfer

SEND        equ 0x3E12    ; Send data
RECV equ 0x3E15 ; Receive data
SENDTO equ 0x3E18 ; Send data to an address (UDP)
RECVFROM equ 0x3E1B ; Receive data from an address (UDP)

SEND: Send data on a TCP socket

  • Input: Socket fd in HL, Buffer pointer in DE, Length in BC, Flags (0)
  • Output: Bytes sent in HL or error

RECV: Receive data from a TCP socket

  • Input: Socket fd in HL, Buffer pointer in DE, Length in BC, Flags (0)
  • Output: Bytes received in HL or error

SENDTO: Send UDP datagram

  • Input: Socket fd in HL, Buffer in DE, Length in BC, Flags (0), sockaddr_in in stack
  • Output: Bytes sent or error

RECVFROM: Receive UDP datagram

  • Input: Socket fd in HL, Buffer in DE, Length in BC, Flags (0), sockaddr_in pointer in stack
  • Output: Bytes received or error

Socket Status

POLL        equ 0x3E1E    ; Poll a list of sockets
POLLALL equ 0x3E21 ; Poll all open sockets
POLLFD equ 0x3E24 ; Poll a single socket

POLL: Check status of multiple sockets

  • Input: Array of pollfd structures
  • Output: Number of ready sockets

POLLFD: Check status of a single socket

  • Input: Socket fd in HL
  • Output: Status bits (BIT_CONN, BIT_DISCON, BIT_RECV)

Network Configuration

GETHOSTBYNAME equ 0x3E27  ; Look up a hostname
IFCONFIG_INET equ 0x3E48 ; Set IPv4 address
IFCONFIG_NETMASK equ 0x3E4B ; Set netmask
IFCONFIG_GW equ 0x3E4E ; Set gateway

GETHOSTBYNAME: Resolve hostname to IP address

  • Input: Hostname string pointer in HL
  • Output: IP address in HL (4 bytes) or error

C API (z88dk)

If you're using C with z88dk, you can use the standard socket API:

#include <sys/socket.h>

int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
// ... configure addr ...
connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
send(sockfd, buffer, length, 0);
recv(sockfd, buffer, length, 0);
close(sockfd);

Socket Address Structure

The sockaddr_in structure is used for addresses:

struct sockaddr_in {
int sin_family; // AF_INET (0)
unsigned int sin_port; // Port number (network byte order)
struct in_addr sin_addr; // IP address
char sin_zero[8]; // Padding
};

struct in_addr {
unsigned long s_addr; // 32-bit IP address
};

Example: TCP Client

; Connect to a server and send data
ld hl, hostname
call GETHOSTBYNAME
jr c, dns_error

; Create socket
ld hl, AF_INET
ld de, SOCK_STREAM
ld bc, 0
call SOCKET
jr c, socket_error
ld (sockfd), hl

; Set up address structure
ld hl, addr_struct
ld (hl), AF_INET
inc hl
ld (hl), 0x50 ; Port 80 (network byte order)
; ... set IP address ...

; Connect
ld hl, (sockfd)
ld de, addr_struct
call CONNECT
jr c, connect_error

; Send data
ld hl, (sockfd)
ld de, message_buffer
ld bc, message_length
call SEND

; Close socket
ld hl, (sockfd)
call CLOSE

Example: TCP Server

; Create socket
ld hl, AF_INET
ld de, SOCK_STREAM
ld bc, 0
call SOCKET
ld (listen_fd), hl

; Bind to port
ld hl, (listen_fd)
ld de, addr_struct
call BIND

; Listen
ld hl, (listen_fd)
ld bc, 5 ; Backlog
call LISTEN

; Accept connection
ld hl, (listen_fd)
ld de, client_addr
call ACCEPT
ld (client_fd), hl

; Receive data
ld hl, (client_fd)
ld de, buffer
ld bc, 1024
call RECV

; Close client socket
ld hl, (client_fd)
call CLOSE

Example: UDP Communication

; Create UDP socket
ld hl, AF_INET
ld de, SOCK_DGRAM
ld bc, 0
call SOCKET
ld (sockfd), hl

; Send datagram
ld hl, (sockfd)
ld de, data_buffer
ld bc, data_length
push de ; sockaddr_in pointer
call SENDTO
pop de

; Receive datagram
ld hl, (sockfd)
ld de, recv_buffer
ld bc, 1024
push de ; sockaddr_in pointer for source
call RECVFROM
pop de

Socket Polling

Polling allows you to check socket status without blocking:

; Poll a socket
ld hl, (sockfd)
call POLLFD

; Check status bits
bit BIT_RECV, a
jr nz, data_ready

bit BIT_CONN, a
jr nz, connected

bit BIT_DISCON, a
jr nz, disconnected

Error Handling

Socket operations can fail for various reasons:

  • Network errors: Connection refused, timeout, network unreachable
  • Resource errors: No sockets available, out of memory
  • Protocol errors: Invalid address, socket not in correct state

Always check the carry flag after socket operations:

call CONNECT
jr c, handle_error
; Connection successful

Best Practices

Socket Lifecycle

  1. Allocate: Use SOCKET to create a socket
  2. Configure: Set up address structures
  3. Connect/Bind: Establish connection or bind to port
  4. Communicate: Send/receive data
  5. Close: Always close sockets when done

Resource Management

  • Close sockets: Don't leak socket file descriptors
  • Check errors: Always verify operations succeeded
  • Handle timeouts: Network operations can take time
  • Poll efficiently: Use polling to avoid blocking

Performance

  • Reuse sockets: Keep connections open when possible
  • Batch operations: Group sends/receives together
  • Use UDP for speed: When reliability isn't critical
  • Poll before blocking: Check status before waiting

Limitations

  • Maximum sockets: Limited number of concurrent sockets
  • Buffer sizes: Limited receive buffer sizes
  • Blocking operations: Some operations may block
  • Network speed: Limited by WiFi connection speed

Next Steps