190 likes | 207 Views
Introduction to Socket Programming. April 2010. What is a socket?. An interface between application and network The application creates a socket The socket type dictates the style of communication connection-oriented vs. connectionless Once configured, the application can
E N D
Introduction to Socket Programming April 2010
What is a socket? • An interface between application and network • The application creates a socket • The socket typedictates the style of communication • connection-oriented vs. connectionless • Once configured, the application can • pass data to the socket for network transmission • receive data from the socket (transmitted through the network by some other host)
SOCK_STREAM TCP sockets reliable delivery in-order guaranteed connection-oriented SOCK_DGRAM UDP sockets unreliable delivery no order guarantees no notion of “connection” socket socket D1 3 2 1 Dest. 3 2 D2 1 App App D3 Two essential types of sockets We’ll look at this one
Client – high level view Create a socket Setup the server address Connect to the server Read/write data Shutdown connection
Some utility functions • Byte Ordering:Host Byte Order to Network Byte Order: htons() , htonl()Network Byte Order to Host Byte Order: ntohs() , ntohl() • IP Address format:Ascii dotted to Binary: inet_aton()Binary to Ascii dotted: inet_ntoa() • Many others exist …… explore the man pages :D
Socket() – A Connection Endpoint • This creates an endpoint for a network connection.int socket(int domain, int type, int protocol)domain = PF_INET (IPv4 communication)type = SOCK_STREAM (TCP) , SOCK_DGRAM (UDP)protocol = 0 (for our discussion) • Example : socket(PF_INET, SOCK_STREAM, 0);This will create a TCP socket. • The call returns a socket descriptor on success and -1 on an error.
Ipv4 socket address structure struct socketaddr_in{ uint8_t sin_len; /*length of the structure (16)*/ sa_falimily_t sin_family /* AF_INT*/ in_port_t sin_port /* 16 bit TCP or UDP port number*/ struct in_addr sin_addr /* 32 bit Ipv4 address */ char sin_zero(8)/* unused*/ } Hostent structure struct hostent{ char * h_name /*official name of host*/ char ** h_aliases; /* pointer ot array of\ pointers to alias name*/ int h_addrtype /* host address type*/ int h_length /* length of address */ char ** h_addr_list /*prt to array of ptrs with \ IPv4 or IPv6 address*/ } Make the socket Socket(int family , int type, int protocol); return nonnegative value for OK, -1 for error Resolve the host struct hostent *gethostbyname( const char *hostname); /*Return nonnull pointer if OK, NULL on error */ unit16_t htons(unit16_t host16bitvaule) /*Change the port number from host byte order to network byte order */ connect(int socketfd, const struct sockaddr * servaddr, socket_t addrlen) /*Perform the TCP three way handshaking*/ Setup the struct Connect int connect_ socket(char *hostname, int port) { int sock; struct sockaddr_in sin; struct hostent *host; sock = socket(AF_ INET, SOCK_ STREAM, 0); if (sock == -1) return sock; host = gethostbyname(hostname); if (host == NULL) { close( sock); return -1; } memset (& sin, 0, sizeof( sin)); sin. sin_ family = AF_ INET; sin. sin_ port = htons(port); sin. sin_ addr.s_ addr = *(unsigned long *) host -> h_ addr_ list[0]; if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) { close (sock); return -1; } return sock; }
Server – high level view Create a socket Bind the socket Listen for connections Accept new client connections Read/write to client connections Shutdown connection
Bind() – Attaching to an IP and Port • A server process calls bind to attach itself to a specific port and IP address.int Bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)sockfd = socket descriptor returned by socket()my_addr = pointer to a valid sockaddr_in structure cast as a sockaddr * pointeraddrlen = length of the sockaddr_in structure • Example : struct sockaddr_in my;my.sin_family = PF_INET;my.sin_port = htons(80);my.sin_addr.s_addr = INADDR_ANY;bzero(&my, 8)bind(sock, (struct sockaddr *)&my, sizeof(my));
Listen() – Wait for a connection • The server process calls listen to tell the kernel to initialize a wait queue of connections for this socket.Int Listen(int sock, int backlog)sock = socket returned by socket()backlog = Maximum length of the pending connections queue • Listen() returns -1 on error (otherwise 0). • Example: Listen(sock, 10);This will allow a maximum of 10 connections to be in pending state.
Listening on a port (TCP) Make the socket Setup up the struct Bind bind(int sockfd, const struct sockaddr * myaddr, socklen_t addrlen); /* return 0 if OK, -1 on error assigns a local protocol adress to a socket*/ int make_ listen_ socket( int port) { struct sockaddr_ in sin; int sock; sock = socket( AF_ INET, SOCK_ STREAM, 0); if (sock < 0) return -1; memset(& sin, 0, sizeof( sin)); sin. sin_ family = AF_ INET; sin. sin_ addr. s_ addr = htonl( INADDR_ ANY); sin. sin_ port = htons( port); if (bind( sock, (struct sockaddr *) &sin, sizeof( sin)) < 0) return -1; if(listen(sock,10) < 0) return -1; return sock; }
Accept() – A new connection ! • Accept is called by a Server process to accept new connections from new clients trying to connect to the server.Int Accept(int socket, (struct sockaddr *)&client, socklen_t *client_len)socket = the socket in listen stateclient = will hold the new client’s informationclient_len = pointer to size of the client structure • Example : struct sockaddr_in client;int len = sizeof(client);Accept(sock, (struct sockaddr *)&client, &len);
Accept() return value accept() returns a new socket descriptor (small positive integer) or -1 on error. After accept returns a new socket descriptor, I/O can be done using the read() and write() system calls. read() and write() operate a little differently on sockets (vs. file operation)!
Send / Recv – Finally Data !! • Send(), Recv() , Read() , Write() etc calls are used to send and receive data .Int send(int sock, void *mesg, size_t len, int flags)Int recv(int sock, void *mesg, size_t len, int flags)sock = A connected socketmesg = Pointer to a buffer to send/receive data from/in .len = Size of the message bufferflags = 0 (for our purpose)The return value is the number of bytes actually sent/received. • Example:char send_buffer[1024];char recv_buffer[1024];int sent_bytes;int recvd_bytes;sent_bytes = send(sock, send_buffer, 1024, 0);recvd_bytes = recv(sock, recv_buffer, 1024, 0);
TCP Server socket() bind() Well-known port TCP Client listen() Socket() accept() blocks until connection from client connect() Connection establishment Data(request) write() read() process request Data(reply) write() read() close() End-of-file notification read() close()
Dealing with blocking calls • Many functions block • accept(), connect(), recv() • For simple programs this is fine • What about complex connection routines • Multiple connections • Simultaneous sends and receives • Simultaneously doing non-networking processing
Dealing with blocking (cont..) • Options • Create multi-process or multi-threaded code • Turn off blocking feature (fcntl() system call) • Use the select() function • What does select() do? • Input: a set of file descriptors • Output: info on the file-descriptors’ status • Therefore, can identify sockets that are “ready for use”: calls involving that socket will return immediately
select function call • int status = select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *Timeout); • Status: # of ready objects, -1 if error • nfds: 1 +largest file descriptor to check • readfds: list of descriptors to check if read-ready • writefds: list of descriptors to check if write-ready • exceptfds: list of descriptors to check if an exception is registered • Timeout: time after which select returns
Four parts of first project • 0: Get build , configure and run the minet stack • 1: HTTP Client • 2: Connection-at-a-time HTTP Server • 3: Simple select-based Multiple-connection-at-a-time server • 4: Complex …. ( Extra Credit )