meta data for this page
  •  

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
courses:ct30a5002:examples [2014/09/02 18:41]
julaakko [UDP client and server]
courses:ct30a5002:examples [2015/11/17 17:59] (current)
julaakko [TCP example]
Line 1: Line 1:
 +====== Example codes ======
  
 +Some example codes for your use.
 +
 +===== Hello World! =====
 +
 +Unpack: {{:​courses:​ct30a5000:​helloworld.tar.gz|}}
 +  * Creates a directory "​helloworld"​
 +  * See README-file in //​helloworld//​ -directory
 +
 +===== UDP client and server =====
 +
 +Unpack: {{:​courses:​ct30a5002:​udpexample2014.tar.gz|}}
 +  * creates a folder "​udpexample"​
 +  * build with **make**
 +  * Run
 +    * Server <​code>​./​udpexample <​port></​code>​
 +    * Client <​code>​./​udpexample <​port>​ <​IP></​code>​
 +
 +===== TCP example =====
 +
 +Unpack {{:​courses:​ct30a5002:​tcpexample2014.tar.gz|}}
 +  * Creates a folder tcpexample
 +  * build with **make**
 +  * Run:
 +    * Server (starts at port 6543) <​code>​./​tcpserver</​code>​
 +    * Client <​code>​./​tcpclient -h <​host/​IP>​ -p <​port></​code>​
 +  * **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., <code bash>​./​tcpclient -h fe80::​7a2b:​cbff:​fea5:​6b92%eth0 -p 6543 -6</​code>​
 +    * 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 {{:​courses:​ct30a5002:​sendtest.tar.gz|}}
 +  * Creates a folder sendtest
 +  * build with **make**
 +    * also other build options ...
 +  * Run:
 +    * Server (given port is TCP, UDP = TCP+1) <​code>​./​sendtests <​port>​ </​code> ​
 +    * Client <​code>​./​sendtestc <​host>​ <​port>​ <amount of bytes to send></​code>​
 +===== SCTP example =====
 +
 +==== Reading material ====
 +
 +SCTP [[http://​tools.ietf.org/​html/​rfc3286|introduction RFC]] and [[http://​tools.ietf.org/​html/​rfc4960|specification RFC]]
 +
 +[[http://​www.ibm.com/​developerworks/​linux/​library/​l-sctp/​|Better networking with SCTP]] by IBM/M. Tim Jones
 +
 +[[http://​datatag.web.cern.ch/​datatag/​WP3/​sctp/​primer.htm|SCTP Primer]] ​
 +
 +[[http://​www.isoc.org/​briefings/​017/​|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 {{:​courses:​ct30a5000:​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:
 +<code bash>
 +# Build client and server (all)
 +make 
 +
 +# Build client and server with debug enabled
 +make debug
 +
 +# Build test client and server
 +make tests
 +</​code>​
 +
 +To run:
 +<code bash>
 +# 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>​
 +</​code>​
 +===== Multicast =====
 +
 +==== Reading material ====
 +
 +[[http://​www.tldp.org/​HOWTO/​Multicast-HOWTO.html|Multicast HOWTO]]
 +
 +[[http://​www.internet2.edu/​multicast/​|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):
 +    * [[http://​docs.oracle.com/​cd/​E19683-01/​806-4125/​sockets-138/​index.html|Sending IPv4 Multicast Datagrams]]
 +    * [[http://​docs.oracle.com/​cd/​E19683-01/​806-4125/​sockets-5/​index.html|Receiving IPv4 Multicast Datagrams]]
 +    * [[http://​docs.oracle.com/​cd/​E19683-01/​806-4125/​sockets-13/​index.html|Sending IPv6 Multicast Datagrams]]
 +    * [[http://​docs.oracle.com/​cd/​E19683-01/​806-4125/​sockets-149/​index.html|Receiving IPv6 Multicast Datagrams]]
 +
 +==== Example code ====
 +
 +Here is a way to use ''​getaddrinfo()''​ and ''​getnameinfo()''​ with multicast addresses.
 +
 +<code c>
 +
 +// 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"​);​
 +</​code>​
 +
 +
 +===== Ncurses game example =====
 +
 +Some tutorials:
 +  * [[http://​hughm.cs.ukzn.ac.za/​~murrellh/​os/​notes/​ncurses.html|A brief programming guide]]
 +  * [[http://​www.tldp.org/​HOWTO/​NCURSES-Programming-HOWTO/​|TLDP Ncurses HowTo]]
 +
 +Example code:
 +  * {{:​courses:​ct30a5000:​ncursesexample.tar.gz|}}
 +  * build with **make**
 +  * Run: <​code>​./​game</​code>​
 +
 +
 +----
 +[[courses:​ct30a5002:​start|CT30A5002 - Games and Networking]]