320 likes | 335 Views
Socket Programming. Carsten Griwodz. What are sockets?. An API between the application and the network Applications send data through the socket over the network to a remote application Applications receive data through the socket from a remote application
E N D
Socket Programming Carsten Griwodz Socket programming
What are sockets? • An API between the application and the network • Applications send data through the socket over the network to a remote application • Applications receive data through the socket from a remote application • Applications control the time and amount of sending and receiving • Operating systems implement the details Socket programming
Application - Controlled by the appliction Process Process Socket Socket Control block with buffers, variables Control block with buffers, variables Controlled by the operating system Internet What are sockets? Socket programming
What are sockets? • At the application level • Datatype: int • Very similar for • all protocols • file descriptors • stdin, stdout • Share functions with • Reading and writing files • Writing to the screen • Reading from the keyboard Socket programming
What are sockets? • Refer to structures in the operating system • The protocol in use • TCP, UDP, … • Protocol-specific state information • Address of the own machine and application • An open, connected TCP socket needs also • Address of the remote machine and application • Buffers • Variables • Timers Socket programming
Using TCP sockets Socket programming
Creating and using a TCP socket • Handshaking • Initial preparation of data transfer • Create a state in the two machines that communicate Socket programming
socket() • The application claims a socket • Call to the function socket() creates a transport control block, and returns a reference to it • The kind of socket is determined at this time • TCP, UDP, … int sock; sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); Socket programming
socket() sock=socket(domain,type,protocol) • PF_INET, SOCK_STREAM and IPPROTO_TCP are constants that are defined in the included files • Many other possibilities exist • domain: PF_UNIX, PF_INET, PF_INET6, … • type: SOCK_STREAM, SOCK_DGRAM,… • protocol: IPPROTO_TCP, IPPROTO_UDP… • PF_INET and SOCK_STREAM request a TCP socket • PF_INET and SOCK_DGRAM request a UDP socket Socket programming
socket() • A TCP state machine is created in closed state CLOSED LISTEN SYN SENT SYN RCVD ESTABLISHED FIN WAIT 1 CLOSE WAIT CLOSING FIN WAIT 2 LAST ACK TIME WAIT Socket programming
Creation of a TCP connection • One application must be the active one • Take the initiative in creating the connection • This side is called the client • The other application must be passive • Be prepared for accepting connections • Expect someone else to takes the initiative • This side is called the server • This use of the words client and server is not entirely consistent with everyday use • For programming this is conventional Socket programming
Goal: Move the TCP state machine to a waiting state Host address is known Define an application address The port TCP server steps /* declarations */ struct sockaddr_in serveraddr; /* Clear the structure */ bzero(&serveraddr, sizeof(serveraddr)); /* Set the address family */ serveraddr.sin_family = AF_INET; /* Allow all own addresses to receive */ serveraddr.sin_addr.s_addr = INADDR_ANY; /* Add the port number */ serveraddr.sin_port = htons(2009); Socket programming
struct sockaddr_in • Define IP addresses and port numbers in the way the Berkeley socket API needs it • htons() • Host-to-network short • Translate an integer value to network format • AF_INET • Constant indicating that Internet protocols will be used • INADDR_ANY • Constant meaning any (Internet) address • In this context: any own Internet address Socket programming
Goal: Move the TCP state machine to a waiting state Host address is known Define an application address The port Add address information to socket Go into waiting state Binding and listing /* bind the address to the socket */ bind(request_sock, (struct sockaddr *)&serveraddr, sizeof serveraddr); /* active listening on the socket */ listen(request_sock, SOMAXCONN); /* wait for connections */ clientaddrlen = sizeof(struct sockaddr_in); sock = accept(request_sock, (struct sockaddr *)&clientaddr, &clientaddrlen); ACCEPT FUNCTION BLOCKS Socket programming
Server: bind(), listen() • bind() • Tells the socket on the server side which address and port number to listen to • A machine can have several addresses • listen(); • Prepares the server for listening to connect requests, and initializes a queue for connect requests • The second parameter defines how long the queue should be • SOMAXCONN • The length of the queue of connection requests • Defined in the includes Socket programming
Server: accept() • Returns a new socket that the server can use to communicate with the client • Take the first connect request from the connect request queue • Wait for the next connect request to arrive if the queue is empty • clientaddr contains information about the client • clientaddrlen must be initialized, so accept knows the size of clientaddr Socket programming
TCP client steps • Goal: Move the server’s and client’s state machines to established state • Server’s host name is known • Server’s host address is unknown • Use the same application address • The port Socket programming
Preparing the client for connecting char* machine = “login.ifi.uio.no”; struct hostent *hostp; struct sockaddr_in serveraddr; int sock; /* Look in DNS for the IP address of the name */ if ((hostp = gethostbyname(machine)) == 0) { fprintf(stderr,“Unknown machine %s\n",machine); exit(1); } bzero((void *) &serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; memcpy(&serveraddr.sin_addr, hostp->h_addr, hostp->h_length); serveraddr.sin_port = htons(2009); • sockaddr_in serveraddr • Needed to specify the server’s address for the socket • gethostbyname() • Takes a hostname • Returns information about that hostname • Including its IP address Socket programming
Preparing the client for connecting /* Connect */ connect(sock, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr_in)); • connect() • Take all the steps to initiate a connection to the server • sock • The own socket • Operating systems fills in own control block implicitly • serveraddr • The address of the TCP server application Socket programming
Client: connect() • Connects client socket to a server that is specified in the address structure • Does NOT return a new socket • The given socket is later used for communicating • serveraddr contains information about the server • The length of serveraddr is not modified Socket programming
Server has left waiting state accept() function returns Processing continues Server: accept() /* bind the address to the socket */ bind(request_sock, (struct sockaddr *)&serveraddr, sizeof serveraddr); /* active listening on the socket */ listen(request_sock, SOMAXCONN); /* wait for connections */ clientaddrlen = sizeof(struct sockaddr_in); sock = accept(request_sock, (struct sockaddr *)&clientaddr, &clientaddrlen); SERVER CAN CONTINUE Socket programming
read() and write() • The call read(sock, buffer, n); • Reads n characters • From socket sock • Stores them in the character array buffer • The call write(sock, buffer, n); • Writes n characters • From character array buffer • To the socket sock Socket programming
read() and write() TCP sender • Typical • retval == -1 • Some kind of error, look at errno • retval == 0 • The connection has been closed • retval n < 2000 • You tried to send too fast • Only n bytes have been sent • Try sending the reset • retval == 2000 • All bytes have been sent • Very untypical • retval < -1 • retval > 2000 • Both cases: • Have you used char retval instead of int retval? char buffer[2000]; int retval; buffer[0] = ‘a’; buffer[1] = ‘b’; buffer[2] = ‘c’; … /* write abcdefghij */ retval = write( sock, buffer, 2000 ); Socket programming
read() and write() TCP receiver • Typical • retval == -1 • Some kind of error, look at errno • retval == 0 • The connection has been closed • retval n < 2000 • Only n bytes have been received • No new data has arrived recently • Try sending the rest • retval == 2000 • All bytes have been received • Very untypical • retval < -1 • retval > 2000 • Both cases: • Have you used char retval instead of int retval? char buffer[2000]; int retval; … /* write abcdefghij */ retval = read( sock, buffer, 2000 ); Socket programming
Closing of sockets Server Client /* Close the socket */ close(sock); /* Close both sockets */ close(sock); close(request_sock); • Note that the semantics of close depends • on the kind of protocol • some possible extra settings • All data that has not been read yet may be thrown away Socket programming
Concurrency • Must solve several tasks at once • Wait for data from communication partners • Notice that a connection has been closed • Read data typed by the user • Listen for client connections (servers only) Socket programming
Concurrency • Use fork to create several processes • Each process waits for one event • Use select • One process waits for several events • Use threads • Similar to fork Socket programming
select() int select( int max_fd, fd_set* read_set, fd_set* write_set, fd_set* except_set, struct timeval* timeout ); • Complicated at first • But very useful • Can wait for activity on many sockets • New connections on request sockets • New data on connected sockets • Closing of a connected socket • Ready-to-send on a socket • Can wait for user input • Can wait for timeouts Socket programming
select() int select( int max_fd, fd_set* read_set, fd_set* write_set, fd_set* except_set, struct timeval* timeout ); • For servers • Serve many clients at once • Handle clients that close connections, clients that crash, … • For simpler cases • Wait for data from chat partner • Wait for typing of the user Socket programming
select() int select( int max_fd, fd_set* read_set, fd_set* write_set, fd_set* except_set, struct timeval* timeout ); • read_set • Arriving connect requests • Arriving data • Closing sockets • write_set • Not often used • Non-blocking send is finished • except_set • Hardly ever used • sendto(.,.,.,MSG_OOB) Socket programming
select() void wait_for_all(int clientsock[], int clients) { fd_set read_set; int i,act,top=0; FD_ZERO(&read_set); for( i=0; i<clients; i++ ) { FD_SET(clientsock[i],&read_set); top = MAX(top,clientsock[i]); } act = select( top+1, &read_set, NULL, NULL, NULL); … } • Using only the read_set is typical • Clear the read_set • Must be done every time • Put all sockets into the read set • Find the highest socket number, add 1 • NULL timeout • Means forever • Call select • waits for arriving data Socket programming
select() void wait_some_time(int sec, int usec) { struct timeval timeout; timeout.tv_sec = sec; timeout.tv_usec = usec; act = select( 0, NULL, NULL, NULL, &timeout ); … } • select can also wait only for a timeout • Without sockets • Timeout parameter • NULL means wait forever • Timeval {5,0} means wait 5 seconds • Timeval {0,0} means don’t wait at all Socket programming