EKT434 Network Programming Socket Introduction
abstract Socket Address Structure Value-Result Argument Byte Ordering Function Byte Manipulation Function
How to Write Network Applications? TCP/IP is implemented inside the OS OS exports the TCP/IP functionalities through SOCKET APIs API: Application Program Interface A set of functions Programmers develop network applications by using SOCKET APIs To learn SOCKET programming Learn some data structures Learn the socket APIs Learn multi-threading
Socket Abstraction Socket is an interface between applications and the network services provided by OS An application sends and receives data through a socket Application SOCKETAPI TCP/IPv4 TCP/IPv6 UNIX
Socket Abstraction (Cont.) Process A data data Process B data socket socket
Socket Abstraction (Cont.) Browser A Web Server Browser B socket socket socket Browser C
Socket Descriptor Data Structure 0 1 2 3 4 Descriptor Table Family: PF_INET Service: SOCK_STREAM Local IP: 111.22.3.4 Remote IP: 123.45.6.78 Local Port: 2249 Remote Port: 3726
How to Create a Socket? The socket API contains a function socket() that can be called to create a socket. E.g.: #include <winsock2.h> SOCKET s; s = socket(af_inet, SOCK_DGRAM, 0) ; The socket is not usable yet. We need to specify more information before using it for data transmission.
Types of Sockets Under protocol family AF_INET Stream socket Uses TCP for connection-oriented reliable communication Identified by SOCK_STREAM s = socket(af_inet, SOCK_STREAM, 0) ; Datagram socket Uses UDP for connectionless communication Identified by SOCK_DGRAM s = socket(af_inet, SOCK_DGRAM, 0) ; RAW socket Uses IP directly Identified by SOCK_RAW Advanced topic.
Review: Structure C structures are collections of related variables under one name. struct employee { char firstname[20]; char lastname[20]; int age; float salary; }; typedef struct employee Employee; Employee em; Employee *pem; /* pointer to structure */ em.salary = 23456; /* dot operator */ pem = &em; /* assign address of em to pem */ pem->salary += 1000; /* struct pointer operator */
IPv4 Socket Address Structure Struct in_addr{ in_addr_t s_addr; /*32bit IPv4 address*/ }; /*network byte ordered*/ struct sockaddr_in { uint8_t sin_len; /* length of structure(16) */ sa_family_t sin_family; /* AF_INET */ in_port_t sin_port; /* 16bit TCP or UDP port number */ /*network byte ordered*/ struct in_addr sin_addr; /* 32bit IPv4 address */ /*network byte ordered*/ char sin_zero[8]; /* unused */ }; /* included in <netinet/in.h> */
Generic Socket address structure Socket address structure protocol structure handling ANSI C : void* <sys/socket.h> : Generic Socket address structure struct sockaddr { uint8_t sa_len; sa_family_t sa_family; /*address family: AF_xxx value*/ char sa_data[14]; /*protocol specific address*/ }
Generic SA structure int bind(int, struct sockaddr *, socklen_t); (example) struct sockaddr_in serv; /*IPv4 socket address structure*/ /* fill in serv{} */ bind(sockfd, (struct sockaddr *) &serv, sizeof(serv));
sockaddr vs. sockaddr_in struct sockaddr struct sockaddr_in 2 bytes sa_family sin_family 2 bytes sin_port 2 bytes 14 bytes sa_data sin_addr 4 bytes sin_zero 8 bytes A pointer to a struct sockaddr_in can be cast to a pointer to a struct sockaddr and vice-versa.
IPv6 Socket Address Structure Struct in6_addr{ uint8_t s6_addr[16]; /*128bit IPv6 address*/ }; /*network byte ordered*/ #define SIN6_LEN /* required for compile-time tests */ struct sockaddr_in6 { uint8_t sin6_len; /* length of structure(24) */ sa_family_t sin6_family; /* AF_INET6*/ in_port_t sin6_port; /* Transport layer port# */ /*network byte ordered*/ uint32_t sin6_flowinfo; /* priority & flow label */ /*network byte ordered*/ struct in6_addr sin6_addr; /* IPv6 address */ /*network byte ordered*/ }; /* included in <netinet/in.h> */
Comparison of socket address structure
Value-Result Argument
Socket address structure pass. Bind, connect, sendto Accept, recvfrom, getsockname, getpeername
Byte Ordering Byte Ordering: Memory is organized in bytes. E.g, a 16-bit integer takes 2 consecutive bytes; a 32-bit integer takes 4 consecutive bytes. Different machines use different host bye orderings: little-endian: least significant byte located at lower memory E.g., Intel 80x86 big-endian: least significant byte located at higher memory E.g., Motorola 68000 These machines may communicate with one another over the network, and they may have different understandings on the same data. Not a problem for data type char
Chaos of Byte Order Memory Memory Address 00001010 A 00010111 A+1 00001110 A+2 00000110 A+3 Big-Endian Computer Send out an integer 169283078 Big-Endian Little-Endian 00001010 00010111 00001110 00000110 00000110 00001110 00010111 00001010 Little-Endian Computer A A+1 A+2 A+3 A+3 A+2 A+1 169283078 68032266 A Receive an integer 68032266!
Solution: Network Byte Order Let s have some regulation! Network byte order is defined as big-endian byte order Integers should be sent out in network byte order The members sin_port and sin_addr in struct sockaddr_in should be in network byte order sin_port: TCP or UDP port number, put into the TCP/UDP header sin_addr: IP address, put into the IP header The member sin_family will not be sent out to the network. So it is not necessary to be in network byte order. If your application needs to transfer integers between two machines, you should transfer them into network byte order. You don t know the type of CPU that executes your program!
Network Byte Order When sending out an integer Transfer it into network byte order by: u_short htons (u_short host_short); u_long htonl (u_long host_long); After receiving an integer Transfer it into (local) host byte order by: u_short ntohs (u_short network_short); u_long ntohl (u_long network_long); Remark: u_short: unsigned 16-bit integer u_long: unsigned 32-bit integer h: host n: network s: short l: long h-to-n-s h-to-n-l n-to-h-s n-to-h-l
Convert the natives! Byte order h : host byte order n : network byte order s : short (16bit) l : long (32bit) uint16_t htons(uint16_t); uint16_t ntohs(uint_16_t); uint32_t htonl(uint32_t); uint32_t ntohl(uint32_t); In_addr values should be stored in network byte order (common mistake)
Determine host byte order #include "unp.h" int main(int argc, char **argv) { } union {short s; un.s = 0x0102; char c[sizeof(short)]; } un; printf("%s: ", CPU_VENDOR_OS); if (sizeof(short) == 2) { if (un.c[0] == 1 && un.c[1] == 2) printf("big-endian\n"); else if (un.c[0] == 2 && un.c[1] == 1) printf("littleendian\n"); else printf("unknown\n"); } else printf("sizeof(short) = %d\n", sizeof(short)); exit(0);
Byte Manipulation Functions: Operating on multibyte fields From 4.2BSD: #include <strings.h> void bzero (void *dest, size_t nbytes); void bcopy (const void *src, void *dest, size_t nbytes); int bcmp (const void *ptr1, const void *ptr2, size_t nbytes); returns: 0 if equal, nonzero if unequal From ANSI C: #include <string.h> void *memset (void *dest, int c, size_t len); void *memcpy (void *dest, const void *src, size_t nbytes); int memcmp (const void *ptr1, const void *ptr2, size_t nbytes); returns: 0 if equal, nonzero if unequal
Address Conversion Functions between ASCII strings and network byte ordered binary values For IPv4 only: ascii and numeric #include <arpa/inet.h> int inet_aton (const char *strptr, struct in_addr *addrptr); returns: 1 if string is valid, 0 on error int_addr_t inet_addr (const char *strptr); returns: 32-bit binary IPv4 addr, INADDR_NONE if error char * inet_ntoa (struct in_addr inaddr); returns: pointer to dotted-decimal string For IPv4 (AF_INET) and IPv6 (AF_INET6): presentation and numeric #include <arpa/inet.h> int inet_pton (int family, const char *strptr, void *addrptr); returns: 1 if OK, 0 if invalid presentation, -1 on error const char *inet_ntop (int family, const void *addrptr, char *strptr, size_t len); returns: pointer to result if OK, NULL on error