* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Introduction - Universität Basel | Informatik
Survey
Document related concepts
Transcript
Computernetzwerke und Sicherheit (CS221) 4. Socket Programming in C 4. März 2011 omas Meyer (basierend auf einem Foliensatz von Christophe Jelger) Departement Mathematik und Informatik, Universität Basel Introduction What is a socket? ❖ ❖ ❖ A socket is a bi-directional communication abstraction (called association) between two processes. A socket is the endpoint of a communication. Sockets is an Application Programming Interface (API) for InterProcess Communication (IPC) process 1 socket e.g. web browser process 2 socket e.g. web server (Mozilla, Internet Explorer) CS221 — FS11 — 4. Socket Programming 2 Introduction ere are may types of sockets ❖ SOCK_STREAM: TCP (connection oriented, guaranteed delivery) ❖ SOCK_DGRAM: UDP (datagram-based communication) ❖ ❖ SOCK_RAW: allows access to the network layer. is can be used to build ICMP messages or custom IP packets. SOCK_PACKET: allows access to the link-layer (e.g. Ethernet). is can be used to build entire frames (e.g. to build a user-space router). CS221 — FS11 — 4. Socket Programming 3 Introduction ere are many domains and (P)rotocol (F)amilies to deal with ❖ PF_INET: IP version 4 (32-bit addresses) ❖ PF_INET6: IP version 6 (128-bit addresses) ❖ PF_UNIX: interprocess communication on the local machine ❖ PF_APPLETALK: Appletalk networks ❖ PF_IPX: Novell Netware networks ❖ ... ❖ PF_ROUTE: access to routing tables (*BSD systems) CS221 — FS11 — 4. Socket Programming 4 Introduction 192.168.1.119 131.152.227.232 HTTP server Port 80 Web browser Port 32816 PF_INET, SOCK_STREAM (IPv4) (TCP) Want to check active sockets on your machine? # netstat -ap -A inet (or inet6, or unix) Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address tcp 0 *:ipp *:* tcp 0 192.168.1.119:32816 www.cs.unibas.ch:www tcp 0 192.168.1.119:32815 www.cs.unibas.ch:www tcp 0 192.168.1.119:32769 clarinet.u-strasb:imaps tcp 0 *:bootpc *:* udp 0 *:ipp *:* udp 0 *:icmp *:* State PID/Program name LISTEN 1437/cupsd ESTABLISHED1621/mozilla-thunde ESTABLISHED1621/mozilla-thunde ESTABLISHED1621/mozilla-thunde 1271/dhclient 1437/cupsd 1720/vmnet-natd CS221 — FS11 — 4. Socket Programming 5 Socket creation int socket (int domain, int type, int protocol); domain: type: protocol: PF_INET, PF_INET6, PF_UNIX, ... SOCK_DGRAM, SOCK_STREAM,... 0=default, or IPPROTO_UDP, IPPROTO_TCP, ... e returned value is a descriptor (i.e., an integer value that uniquely identifies the socket among other descriptors such as sockets, files, pipes, etc.) Example: int my_socket; my_socket = socket(AF_INET, SOCK_STREAM, 0); CS221 — FS11 — 4. Socket Programming 6 Socket address configuration struct sockaddr_in { short int sin_family; unsigned short int sin_port; struct in_addr sin_addr; unsigned char sin_zero[8]; }; struct in_dadr { unsigned long s_addr; }; /* /* /* /* domain*/ port number */ IP address */ padding with zeros */ ❖ Purpose of structure: easy access to socket parameters ❖ Basic structure: sockaddr ❖ But one should always use the appropriate sockaddr_XXX when accessing a specific structure type (e.g. sockaddr_in) sockaddr family sockaddr_in family blob port addr zero CS221 — FS11 — 4. Socket Programming 7 Watch the conversions!!! Convert multibyte integers ❖ 50966 in decimal = c734 in hexadecimal ❖ there are two ways to encode this number in 32 bits: • 34-c7-00-00 = host byte order (little-endian, Intel) • 00-00-c7-34 = host byte order (big-endian, Motorola, IBM) memory n...n+3 • 00-00-c7-34 = network byte order (big-endian, for all machines!) ❖ ❖ sin_port and sin_addr MUST be in network byte order When building a packet (SOCK_RAW or SOCK_PACKET), all data fields must be in network byte order! CS221 — FS11 — 4. Socket Programming 8 Integer conversion functions ❖ htonl host to network long (to convert a long integer (32 bit) from host to network byte order, before tx) ❖ htons host to network short (to convert a short integer (16 bit) from host to network byte order, before tx) ❖ ntohl network to host long (after rx) ❖ ntohs network to host short (after rx) Caution: Don’t convert chars! Example: struct sockaddr_in webyahooAddr; webyahooAddr.sin_family = AF_INET; webyahooAddr.sin_port = htons(80); webyahooAddr.sin_addr.s_addr = inet_addr(“217.12.3.11”); memset(&webyahooAddr.sin_zero, ‘\0’, 8); CS221 — FS11 — 4. Socket Programming 9 Datagram-based communication Function calls with UDP (SOCK_DGRAM) station 1 station 2 socket() socket() bind() bind() sendto()/recvfrom() close() data sendto()/recvfrom() close() CS221 — FS11 — 4. Socket Programming 10 Binding of the socket (to an address) Bind = Assign IP address and port number to socket Example: int mySock; struct sockaddr_in locAddr; mySock = socket(PF_INET, SOCK_STREAM, 0); /* or SOCK_DGRAM */ locAddr.sin_family = AF_INET; locAddr.sin_port = htons(0); /* let the system choose */ locAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* any addr of machine */ memset(&locAddr, ‘\0’, 8); bind(mySock, (struct sockaddr*)&locAddr, sizeof(locAddr)); CS221 — FS11 — 4. Socket Programming 11 Binding of the socket (to an address) Read-back auto values ❖ When calling bind() with sin_port=0, the value chosen by the system is not saved in the structure. ❖ We must use getsockname() to update the structure. Example: int length; getsockname(mySock, (struct sockaddr*)&locAddr, &length); /* note: length is an output argument; we have to pass its address */ /* the port number is now updated and can be displayed: but remember to convert to host byte order! */ printf(“Port chosen by the system is %d, ntohs(locAddr.sin_port)); CS221 — FS11 — 4. Socket Programming 12 Stream-based communication Walk-through example: TCP Echo Server client socket() server bind() socket() bind() listen() connect() accept() send()/recv() send()/recv() close() close() CS221 — FS11 — 4. Socket Programming 13 Echo server: Create socket /* create socket for incoming connections */ int srvSock = socket(PF_INET, SOCK_STREAM, 0); client socket() bind() server socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() CS221 — FS11 — 4. Socket Programming 14 Echo server: Bind local address struct sockaddr_in srvAddr; srvAddr.sin_family = AF_INET; /* IPv4 address srvAddr.sin_port = htons(8080); /* local server port srvAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* any interf. memset(&srvAddr.sin_zero, ‘\0’, 8); /* padding */ */ */ */ bind(srvSock, (struct sockaddr*)&srvAddr, sizeof(srvAddr)); client socket() server bind() socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() CS221 — FS11 — 4. Socket Programming 15 Echo server: Listen to incoming connections /* listen for incoming connections */ listen(srvSock, MAXPENDING); client socket() bind() server socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() CS221 — FS11 — 4. Socket Programming 16 Echo server: Accept incoming connections for (;;) { struct sockaddr_in cliAddr; /* client address */ int cliAddrLen = sizeof(cliAddr); int cliSock; /* socket for comm. to client */ cliSock = accept(srvSock, (struct sockaddr*)&cliAddr, &cliAddrLen); client socket() server bind() socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 17 Echo Server: Accept incoming connections Server is now blocked, waiting for an incoming connection: client socket() bind() server socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 18 Echo client: Create socket /* create TCP socket for outgoing connection */ int cliSock = socket(PF_INET, SOCK_STREAM, 0); client socket() cliSock server bind() socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 19 Echo Client: Bind local address (optional) struct sockaddr_in cliAddr; cliAddr.sin_family = AF_INET; /* IPv4 cliAddr.sin_port = 0; /* any port cliAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* any memset(&srvAddr.sin_zero, ‘\0’, 8); /* address is fine interf. padding */ */ */ */ bind(cliSock, (struct sockaddr*)&cliAddr, sizeof(cliAddr)); client socket() bind() cliSock server socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 20 Echo Client: Connect to server struct sockaddr_in srvAddr; srvAddr.sin_family = AF_INET; /* IPv4 address srvAddr.sin_port = htons(8080); /* server port srvAddr.sin_addr.s_addr = inetaddr(“1.2.3.4”); /* server IP memset(&srvAddr.sin_zero, ‘\0’, 8); /* padding */ */ */ */ connect(cliSock, (struct sockaddr*)&srvAddr, sizeof(srvAddr)); client socket() cliSock server bind() socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 21 Echo Server: Accept incoming connections cliSock = accept(srvSock, (struct sockaddr*)&cliAddr, &cliAddrLen); Blocking call accept() returns cliSock is the socket descriptor for communication with the client client socket() bind() cliSock server socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 22 Echo Client: Send a message and wait for reply char msg[] = “This is a test.”; send(cliSock, msg, strlen(msg), 0); /* wait for reply by calling recv() (not shown here) */ client socket() cliSock server bind() socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 23 Echo Server: Receive and send same messages #define BUFSIZE 32 char buf[BUFSIZE]; int bytesRecv; bytesRecv = recv(cliSock, buf, BUFSIZE, 0); while (bytesRecv > 0) /* zero indicates end of transmission */ { send(cliSock, buf, bytesRecv, 0); /* echo */ bytesRecv = recv(cliSock, buf, BUFSIZE, 0); } client socket() bind() cliSock server socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 24 Echo Server: Close connection (and accept next) for (;;) { ... cliSock = accept(srvSock, (struct sockaddr*)&cliAddr, &cliAddrLen); ... close(cliSock); } client socket() cliSock server bind() socket() srvSock bind() listen() connect() accept() send()/recv() send()/recv() close() close() cliSock CS221 — FS11 — 4. Socket Programming 25 TCP Socket Features ❖ ❖ ❖ e client must know the server’s address/port. e server must only know its own port! Streaming socket: Transmission/Reception of a byte “stream” ❖ No correlation between bytes and segments (packets). Segmentation of the byte stream is out of the user’s control (due to TCP’s Flow Control) ❖ client send(“This is a test”); recv(“Hello world”); server recv() recv() recv() send() send() -> -> -> -> -> “This i”; “s a te”; “st”; “Hello “ “world”; CS221 — FS11 — 4. Socket Programming 26 TCP Socket Features ❖ ❖ close() is used to terminate a connection analogous to EOF (end-of-file) client server send(...); while (recv(...) > 0) { send(...) } close(); close(); ❖ Caution: Does not work with datagram socket ❖ e.g. UDP ❖ not connection-oriented = no close-notification CS221 — FS11 — 4. Socket Programming 27 Blocking calls Be careful: calls are blocking! ❖ A call to recv(), send(), recvfrom(), and sendto() is by default a blocking call. Example: recvfrom(...); sendto(...); /* call blocks until a message is received */ e program will not be able to send if it does not receive anything! ❖ ❖ Solution 1: use the select() function Solution 2: multi-threaded applications CS221 — FS11 — 4. Socket Programming 28 The select() function ❖ ❖ Used to monitor a set of descriptors (e.g. sockets, files, pipes, stdin). select() blocks until an event on the observed descriptors occurs: If we check a set in order to trigger read operations, select() returns the set that has data ready to be read. ❖ If select() is used in a loop, the initial set of descriptors must then always be initialized properly before re-calling ❖ select() ❖ e blocking behavior of select() can be changed by specifying a timeout value (last function argument). CS221 — FS11 — 4. Socket Programming 29 Using the select() function Example: a server wants to check two sockets for data to read /* the two socket descriptors are sock1 and sock2; let sockmax = (sock1 > sock2 ? sock1 : sock2) */ /* we first need a set of file descriptors */ fd_set readfds, backup; /* we initialize the set and add sock1 and sock2 to it */ FD_ZERO(&readfds); FD_SET(sock1, &readfds); FD_SET(sock2, &readfds); backup = readfds; /* used to save the original state */ for (;;) { select(sockmax, &readfds, NULL, NULL, NULL); if (FD_ISSET(sock1, &readfds)) recv(sock1, buf, MAX_LEN, 0); if (FD_ISSET(sock2, &readfds)) recv(sock2, buf, MAX_LEN, 0); readfds = backup; /* set readfds to initial state */ CS221 — FS11 — 4. Socket Programming } 30 Multithreaded server ❖ Spawn a new thread for each accepted connection for (;;) { cliSock = accept(srvSock, (struct sockaddr *)&cliAddr, &cliAddrLen); pid = fork(); if (pid == 0) /* child thread */ { close(srvSock); dostuff(cliSock); exit(0); } else /* parent thread */ { close(cliSock); /* continue in while loop: accept next connection... */ } } CS221 — FS11 — 4. Socket Programming 31 Handle errors! ❖ ❖ Socket programming can easily lead to many errors. It is mandatory to check for errors! (for clarity, this is not done in these slides) Example: if (bind(mySock, (struct sockaddr*)&sockAddr, sizeof(sockaddr) < 0) { perror(“Bind: “); /* prints out an explicit error message */ exit(-1); } ❖ Use perror() with all calls! (accept, connect, ...) CS221 — FS11 — 4. Socket Programming 32 Summary ❖ ❖ ❖ ❖ ❖ ❖ ❖ ❖ e socket API provides user-level abstractions for communication associations. One API for different communication types streaming, datagram-oriented, connection-oriented, connection-less and different protocols e.g. UDP, TCP, interprocess communiction socket(), accept() “creates” new socket descriptor close() “destroys” the descriptor bind() configures/binds an address to a socket connect(), accept() to establish a connection-oriented session send()/recv() to send over pre-configured socket sendto()/recvfrom() to configure remote side on-the-fly CS221 — FS11 — 4. Socket Programming 33