740 likes | 887 Views
Socket Network Programming 02/11/2008. Admin. Programming assignment 1 update. Recap: P2P Scalability. BitTorrent as an example a swarming protocol each peer is given a set (~50) of peers upon joining piece selection random at startup and (local) rarest after that peer selection
E N D
Admin. • Programming assignment 1 update
Recap: P2P Scalability • BitTorrent as an example • a swarming protocol • each peer is given a set (~50) of peers upon joining • piece selection • random at startup and (local) rarest after that • peer selection • periodically unchoke a few (4) peers with the highest rates sending to me • optimistic unchoking
P2 P1 P1 P3 SP: 9157 client IP: A DP: 9876 Client IP:B server IP: S SP: 5775 SP: 9876 SP: 9876 DP: 9876 DP: 9157 DP: 5775 UDP: Connectionless Demux DatagramSocket serverSocket = new DatagramSocket(9876); Source Port (SP) provides “return address”
create socket, clientSocket = DatagramSocket() Recap: UDP Client Server (running on hostid) create socket, port=x, for incoming request: serverSocket = DatagramSocket( x ) Create datagram using (hostid, x) as (dest addr. port),send request using clientSocket read request from serverSocket generate reply, create datagram using client host address, port number write reply to serverSocket read reply from clientSocket close clientSocket • Create socket with port number: DatagramSocket sSock = new DatagramSocket(9876); • If no port number is specified, the OS will pick one
UDP Provides Multiplexing/Demultiplexing server client 128.36.232.5128.36.230.2 198.69.10.10 UDP socket space UDP socket space address: {198.69.10.10:1500} snd/recvbuf: address: {*:9876} snd/recvbuf: local port local address address: {198.69.10.10:4343} snd/recvbuf: address: {128.36.232.5:53} snd/recvbuf: Packet demutiplexing is based on (dst address, dst port) at dst %netstat –u –n -a
Example: Java server (UDP) import java.io.*; import java.net.*; class UDPServer { public static void main(String args[]) throws Exception { DatagramSocket serverSocket = new DatagramSocket(9876); byte[] receiveData = new byte[1024]; byte[] sendData = new byte[1024]; while(true) { DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); serverSocket.receive(receivePacket); Create datagram socket at port 9876 Create space for received datagram Receive datagram
Example: Java server (UDP), cont String sentence = new String(receivePacket.getData()); InetAddress IPAddress = receivePacket.getAddress(); int port = receivePacket.getPort(); String capitalizedSentence = sentence.toUpperCase(); sendData = capitalizedSentence.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); serverSocket.send(sendPacket); } } } Get IP addr port #, of sender Create datagram to send to client Write out datagram to socket End of while loop, loop back and wait for another datagram
Example: Java client (UDP) import java.io.*; import java.net.*; class UDPClient { public static void main(String args[]) throws Exception { BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); DatagramSocket clientSocket = new DatagramSocket(); InetAddress IPAddress = InetAddress.getByName("hostname"); byte[] sendData = new byte[1024]; byte[] receiveData = new byte[1024]; String sentence = inFromUser.readLine(); sendData = sentence.getBytes(); Create input stream Create client socket Translate hostname to IP address using DNS
Example: Java client (UDP), cont. Create datagram with data-to-send, length, IP addr, port DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876); clientSocket.send(sendPacket); DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); clientSocket.receive(receivePacket); String modifiedSentence = new String(receivePacket.getData()); System.out.println("FROM SERVER:" + modifiedSentence); clientSocket.close(); } } Send datagram to server Read datagram from server
P2 P1 P1 P3 SP: 9157 client IP: A DP: 9876 Client IP:B server IP: S SP: 5775 SP: 9876 SP: 9876 DP: 9876 DP: 9157 DP: 5775 UDP Connectionless Demux DatagramSocket serverSocket = new DatagramSocket(9876); Source Port (SP) provides “return address”
Source IP: B Dest IP: S source port: x dest. port: 80 Source IP: B Dest IP: S source port: y dest. port: 80 Source IP: A Dest IP: S source port: x dest. port: 80 Recap: TCP Provides Connection-Oriented Demux Web client host B TCP separates data packetsfrom different peers intodifferent sockets Web server S Web client host A Web server
Client must contact server server process must first be running server must have created socket (door) that welcomes client’s contact Client contacts server by: creating client-local TCP socket specifying IP address, port number of server process When client creates socket: client TCP establishes connection to server TCP When contacted by client, server TCP creates new socket for server process to communicate with client allows server to talk with multiple clients source port numbers used to distinguish clients TCP provides reliable, in-order transfer of bytes (“pipe”) between client and server application viewpoint Socket Programming with TCP
TCP socket identified by 4-tuple: source IP address source port number dest IP address dest port number recv host uses all four values to direct segment to appropriate socket server can easily support many simultaneous TCP sockets: different connections/sessions are automatically separated into different sockets TCP Connection-Oriented Demux
SP: x SP: y P1 P1 P2 P4 P3 P6 P5 client IP: A DP: 80 DP: 80 Connection-Oriented Demux S-IP: B D-IP: S SP: x DP: 80 Client IP:B server IP: S S-IP: A S-IP: B D-IP: S D-IP: S
state: listening address: {*:6789, *:*} completed connection queue: sendbuf: recvbuf: state: starting address: {198.69.10.10:1500, *:*} sendbuf: recvbuf: state: listening address: {*:25, *:*} completed connection queue: sendbuf: recvbuf: state: listening address: {*:25, *:*} completed connection queue: sendbuf: recvbuf: Under the Hood:TCP Multiplexing server client 128.36.232.5128.36.230.2 198.69.10.10 TCP socket space TCP socket space local port local addr remote port remote addr %netstat –-tcp –all –l -n
state: listening address: {*:6789, *.*} completed connection queue: sendbuf: recvbuf: state: connecting address: {198.69.10.10:1500, 128.36.232.5:6789} sendbuf: recvbuf: state: listening address: {*.25, *.*} completed connection queue: sendbuf: recvbuf: state: listening address: {*.25, *.*} completed connection queue: sendbuf: recvbuf: Example: Client Initiates Connection server client 128.36.232.5128.36.230.2 198.69.10.10 TCP socket space TCP socket space
state: listening address: {*:6789, *:*} completed connection queue: {128.36.232.5.6789, 198.69.10.10.1500} sendbuf: recvbuf: state: connected address: {198.69.10.10:1500, 128.36.232.5:6789} sendbuf: recvbuf: state: listening address: {*:25, *:*} completed connection queue: sendbuf: recvbuf: state: listening address: {*:25, *:*} completed connection queue: sendbuf: recvbuf: Example: TCP Handshake Done server client 128.36.232.5128.36.230.2 198.69.10.10 TCP socket space TCP socket space
state: listening address: {*.6789, *:*} completed connection queue: sendbuf: recvbuf: state: connected address: {198.69.10.10.1500, 128.36.232.5:6789} sendbuf: recvbuf: state: established address: {128.36.232.5:6789, 198.69.10.10.1500} sendbuf: recvbuf: state: listening address: {*.25, *:*} completed connection queue: sendbuf: recvbuf: state: listening address: {*.25, *:*} completed connection queue: sendbuf: recvbuf: Example: Server accept() server client 128.36.232.5128.36.230.2 198.69.10.10 TCP socket space TCP socket space Packet demutiplexing is based on (dst addr, dst port, src addr, src port) Packet sent to the socket with the best match!
create socket, connect to hostid, port=x create socket, port=x, for incoming request: clientSocket = Socket() welcomeSocket = ServerSocket(x) TCP connection setup wait for incoming connection request connectionSocket = welcomeSocket.accept() send request using clientSocket read request from connectionSocket write reply to connectionSocket read reply from clientSocket close connectionSocket close clientSocket Client/server socket interaction: TCP Server (running on hostid) Client
Example client-server app: 1) client reads line from standard input (inFromUser stream) , sends to server via socket (outToServer stream) 2) server reads line from socket 3) server converts line to uppercase, sends back to client 4) client reads, prints modified line from socket (inFromServer stream) Example Client process client TCP socket
Example: Java client (TCP) import java.io.*; import java.net.*; class TCPClient { public static void main(String argv[]) throws Exception { String sentence; String modifiedSentence; BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); Socket clientSocket = new Socket(“server.name", 6789); DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); Create input stream Create client socket, connect to server Create output stream attached to socket
Example: Java client (TCP), cont. Create input stream attached to socket BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); sentence = inFromUser.readLine(); outToServer.writeBytes(sentence + '\n'); modifiedSentence = inFromServer.readLine(); System.out.println("FROM SERVER: " + modifiedSentence); clientSocket.close(); } } Send line to server Read line from server
Example: Java server (TCP) import java.io.*; import java.net.*; class TCPServer { public static void main(String argv[]) throws Exception { String clientSentence; String capitalizedSentence; ServerSocket welcomeSocket = new ServerSocket(6789); while(true) { Socket connectionSocket = welcomeSocket.accept(); BufferedReader inFromClient = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); Create welcoming socket at port 6789 Wait, on welcoming socket for contact by client Create input stream, attached to socket
Example: Java server (TCP), cont DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream()); clientSentence = inFromClient.readLine(); capitalizedSentence = clientSentence.toUpperCase() + '\n'; outToClient.writeBytes(capitalizedSentence); } } } Create output stream, attached to socket Read in line from socket Write out line to socket End of while loop, loop back and wait for another client connection
Outline • Recap • Socket programming API • UDP • TCP • implementing a web server
Example: WebServer • A simple web server which supports only simple HTTP/1.0 http://zoo.cs.yale.edu/classes/cs433/programming/examples-java-socket/WebServer/
128.36.232.5128.36.230.2 TCP socket space state: listening address: {*.6789, *.*} completed connection queue: sendbuf: recvbuf: state: established address: {128.36.232.5:6789, 198.69.10.10.1500} sendbuf: recvbuf: state: listening address: {*.25, *.*} completed connection queue: sendbuf: recvbuf: WebServer Flow Create ServerSocket(6789) connSocket = accept() read request from connSocket read local file write file to connSocket close connSocket Discussion: what does each step do and how long does it take?
Writing High Performance Servers: Major Issues • Many socket/IO operations can cause a process to block, e.g., • accept: waiting for new connection; • read a socket waiting for data or close; • write a socket waiting for buffer space; • I/O read/write for disk to finish • Thus a crucial perspective of network server design is the concurrency design (non-blocking) • for high performance • to avoid denial of service • Concurrency is also important for clients!
Writing High Performance Servers: Using Multi-Threads • Using multiple threads • so that only the flow processing a particular request is blocked • Java: extends Thread or implements Runnable interface Example: a Multi-threaded WebServer, which creates a thread for each request
Problems of Multi-Thread Server • High resource usage, context switch overhead, contended locks • Too many threads throughput meltdown, response time explosion • In practice: bound total number of threads
Event-Driven Programming • Event-driven programming, also called asynchronous i/o • Using Finite State Machines (FSM) to monitor the progress of requests • Yields efficient and scalable concurrency • Many examples: Click router, Flash web server, TP Monitors, etc. • Java: asynchronous i/o • for an example see: http://www.cafeaulait.org/books/jnp3/examples/12/
Async I/O in Java • An important class is the class Selector, which is a multiplexer of selectable channel objects • example channels: DatagramChannel, Pipe, ServerSocketChannel, SocketChannel • use configureBlocking(false) to make a channel non-blocking • A selector may be created by invoking the open method of this class
Async I/O in Java Selector • A selectable channel registersevents (called a SelectionKey) with a selector with the register method • A SelectionKeyobject contains two operation sets • interest Set • ready Set • A SelectionKey object has an attachment which can store data • often the attachment is a buffer Selectable Channel register Selection Key
Async I/O in Java • Callselect(or selectNow(), or select(int timeout)) to check for ready events, called the selected key set • Iterate over the set to process all ready events
Problems of Event-Driven Server • Difficult to engineer, modularize, and tune • Little OS and tool support: ‘‘roll your own’’ • No performance/failure isolation between FSMs • FSM code can never block (but page faults, garbage collection may still force a block) • thus still need multiple threads
Example 1: A Relay TCP Client fgets writen TCP client TCP server readn fputs Check the code at http://zoo.cs.yale.edu/classes/cs433/programming/examples/tcpclient
Connectionless UDP: Big Picture server client socket(): create socket sd=Socket(): create socket write()/sendto(): send packets to server, by specifying receiver address and port number bind(sd, …): specify socket local IP address and port number read()/recv(): receive packets close(): done close(): done
TCP connection setup Connection-oriented: Big Picture(C version) server client sd=socket(): create socket socket(): create socket bind(sd, …): specify socket address optional bind(): specify socket address listen(sd, …): specify that socket sd is a listening socket connect(): initialize TCP handshake;return until TCP handshake is done sd2=accept(sd, …): get a connected connection from the queue for socket sd;create a new socket identified by sd2 read()/write(): do IO on the socket read()/write(): do IO on socket sd2 close(): done close(sd2): done
Unix Programming: Mechanism • UNIX system calls and library routines (functions called from C/C++ programs) • %man 2 <function name> • A word on style: check all return codesif ((code = syscall()) < 0) { perror("syscall"); }
Creating Sockets #include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol); • creates an endpoint for communication • return value: -1 if an error occurs; otherwise the return value is a descriptor referencing the socket • what are the possible outcomes of this system call?
Creating Sockets: Parameters • domain: address family (protocol family) • determine address structure • e.g. AF_UNIX, AF_INET, AF_INET6 • we will use AF_INET only • type : service of a socket • e.g. SOCK_DGRAM provides unreliable, connectionless service • e.g. SOCK_STREAM provides connection-oriented reliable byte-stream service
Creating Sockets: Parameters (cont.) • protocol : specifies particular protocol • Usually already defined by domain and type (e.g. TCP for AF_INET and SOCK_STREAM; UDP for AF_INET and SOCK_DGRAM) • we will use 0 (default protocol) • Example if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) { perror(“socket”); exit(1);}
Binding the Address for a Socket #include <sys/types.h> #include <sys/socket.h> int bind(int sd, struct sockaddr *my_addr, socklen_t addrlen); • assigns the local address of a socket • return value: -1 if an error occurs; otherwise 0 • what are the possible outcomes of this system call?
Socket Address • Several types of addresses • We will use sockaddr_in (<netinet/in.h>) struct sockaddr_in { sa_family_t sin_family; /*AF_INET*/ uint16_t sin_port; /* network order*/ struct in_addr sin_addr;};struct in_addr { uint32_t s_addr; /* network order*/}; Two types of byte ordering: little endian, and big endian
Internet Addresses and Ports • sin_port • 16 bits • 0-1024 reserved for system • well-known ports are important • If you specify 0, the OS picks a port • s_addr • 32 bits • INADDR_ANY for any local interface address
Internet Addresses and Ports: Example struct sockaddr_in myaddr; bzero( (char*)myaddr, sizeof(myaddr) ); myaddr.sin_family = AF_INET; myaddr.sin_port = htons(80); /* bind to HTTP port*/ myaddr.sin_addr.s_addr = htos(INADDR_ANY); /* any address*/ if ( (bind(sockfd, (struct sockaddr*)&myaddr, sizeof(myaddr)) < 0 ) { perror(“bind”); exit(1); }