Example codes

Some example codes for your use.

Hello World!

Unpack: helloworld.tar.gz

  • Creates a directory “helloworld”
  • See README-file in helloworld -directory

UDP client and server

Unpack: udpexample2014.tar.gz

  • creates a folder “udpexample”
  • build with make
  • Run
    • Server
      ./udpexample <port>
    • Client
      ./udpexample <port> <IP>

TCP example

Unpack tcpexample2014.tar.gz

  • Creates a folder tcpexample
  • build with make
  • Run:
    • Server (starts at port 6543)
      ./tcpserver
    • Client
      ./tcpclient -h <host/IP> -p <port>
  • NOTES:
    • Since in the classroom 6218 the IPv6 network is link local, you have to add the interface at the end of the IPv6 address. E.g.,
      ./tcpclient -h fe80::7a2b:cbff:fea5:6b92%eth0 -p 6543 -6
    • Note that server accepts only IPv6 connections, therefore, IPv4 addresses in numeric format cannot be used but hostnames work (IPv4-mapped IPv6 address)

TCP + UDP example for sending data from client to server

Unpack sendtest.tar.gz

  • Creates a folder sendtest
  • build with make
    • also other build options …
  • Run:
    • Server (given port is TCP, UDP = TCP+1)
      ./sendtests <port> 
    • Client
      ./sendtestc <host> <port> <amount of bytes to send>

SCTP example

Reading material

SCTP introduction RFC and specification RFC

Better networking with SCTP by IBM/M. Tim Jones

SCTP Primer

Why is SCTP needed given TCP and UDP are widely available? By Randall Stewart, Paul D. Amer

UNIX Network Programming Volume 1 Third Edition, W. Richard Stevens, Bill Fenner, Andrew M. Rudoff, ISBN 0-13-1441155-1, Suggested pages: 267-286 (for function and notification event structures).

Example code

2012 version sctp_demo2012.tar.gz

Required packages for Debian/Ubuntu (same for other distros?) to develop applications on top of SCTP: libsctp-dev, libsctp1.

Build with:

# Build client and server (all)
make 
 
# Build client and server with debug enabled
make debug
 
# Build test client and server
make tests

To run:

# Server: give port and some of the following (optional):
# addrinfo - use getaddrinfo(), i.e. use passive addresses (any)
# ifaddrs - [default] use getifaddrs(), use the actual addresses from running interfaces
# combine - Use first ifaddrs() to get all of the addresses then use getnameinfo() and getaddrinfo() to fill structs
./testsctps <port> <addrinfo|ifaddrs|combined>
 
# Client: give IP/hostname and port
./testsctpc <IP|host> <port>

Multicast

Reading material

Multicast HOWTO

Multicast Working Group

Oracle.com Programming Interfaces Guide documentation for SOLARIS (yes, SOLARIS is UNIX and Linux is not UNIX but these pages explain multicast in informative manner):

Example code

Here is a way to use getaddrinfo() and getnameinfo() with multicast addresses.

// Sockets
int multicastsocket = -1, peersocket = -1;
 
int in_addr_length = sizeof(struct in_addr);
 
// For storing addresses and ports
char hostbuffer[NI_MAXHOST] = {0}; // Set the multicast address here
char portbuffer[NI_MAXSERV] = {0}; // Set the port here
char peerportbuffer[NI_MAXSERV] = {0}; // Set the port for incoming connections here
 
char buffer[MESSAGELENGTH] = {0};
 
// For getaddrinfo()
struct addrinfo *result = NULL, *iter = NULL;
struct addrinfo hints = { .ai_flags = AI_NUMERICHOST,
                          .ai_family = AF_INET,
                          .ai_socktype = SOCK_DGRAM,
                          .ai_protocol = IPPROTO_UDP};
 
// The multicast address is stored here
struct sockaddr mc_sending_addr:
memset(&mc_sending_addr,0,sizeof(mc_sending_addr));
 
// Who sent us data
struct sockaddr receiving_addr;
memset(&receiving_addr,0,sizeof(receiving_addr));
 
// Multicast structure
struct ip_mreq multicast;
memset(&multicast,0,sizeof(multicast));
 
// First fill multicast & sending address
if(getaddrinfo(hostbuffer,portbuffer,&hints,&result)) perror("Cannot resolve multicast address");
 
for(iter = result; iter != NULL; iter = iter->ai_next) {
 
  // Set the multicast address (since we need the struct in_addr this is not so portable...)
  memcpy(&multicast.imr_multiaddr, &((struct sockaddr_in*)iter->ai_addr)->sin_addr,in_addr_length);
 
  // Send address - the multicast address
  memcpy(&mc_sending_addr,iter->ai_addr,iter->ai_addrlen);
}
freeaddrinfo(result);
 
// Then get the listening address (any), using the port defined for multicast
hints.ai_flags = AI_PASSIVE;
if(getaddrinfo(NULL,portbuffer,&hints,&result)) perror("Cannot get listening address");
 
for(iter = result; iter != NULL; iter = iter->ai_next) {
 
  // Create socket and bind it
  if((multicastsocket = socket(iter->ai_family,iter->ai_socktype,iter->ai_protocol)) < 0) perror("Cannot create socket");
  if(bind(multicastsocket,iter->ai_addr,iter->ai_addrlen)) perror("Cannot bind to address");
 
  // Set the any-address as interface for multicast
  memcpy(&multicast.imr_interface,&((struct sockaddr_in*)iter->ai_addr)->sin_addr,sin_length);
}
freeaddrinfo(result);
 
// And with same approach get the peer listening address, using the peer port (and previously set hints with AI_PASSIVE)
if(getaddrinfo(NULL,peerportbuffer,&hints,&result)) perror("Cannot get peer listening address");
 
for(iter = result; iter != NULL; iter = iter->ai_next) {
  // Create socket and bind it
  if((peersocket = socket(iter->ai_family,iter->ai_socktype,iter->ai_protocol)) < 0) perror("Cannot create socket");
  if(bind(peersocket,iter->ai_addr,iter->ai_addrlen)) perror("Cannot bind to address");
}
freeaddrinfo(result);
 
// Finally we can join (add membership) to multicast group
if(setsockopt(multicastsocket,IPPROTO_IP,IP_ADD_MEMBERSHIP,&multicast,sizeof(multicast)) < 0)
  perror("Error joining multicastgroup");
 
...
 
// when we receive something from multicast
n = recvfrom(multicastsocket,buffer,MESSAGELENGTH,0,&receiving_addr,&length);
 
// Get the address
if((getnameinfo((struct sockaddr*)&recv_addr,length,hostbuffer,NI_MAXHOST,portbuffer,NI_MAXSERV,NI_NUMERICSERV)) != 0) perror("Cannot get IP");
 
// 1. Get the port from message
// 2. Replace the port in portbuffer with the one in the message
// 3. Use getaddrinfo to fill in struct
hints.ai_flags = 0;
if(getaddrinfo(NULL,portbuffer,&hints,&result)) perror("Cannot fill peer address");
 
// 4. Use the struct sockaddr in the result to send data to new port on that host
 
...
 
// And drop the membership before quitting
if(setsockopt(multicastsocket,IPPROTO_IP,IP_DROP_MEMBERSHIP,&multicast,sizeof(multicast)) < 0)
  perror("Error leaving multicastgroup");

Ncurses game example