400 likes | 416 Views
Berkeley Sockets Details for everyday use. Carsten Griwodz. Data types. Basic data types Have a certain number of bits Not very important in platform-dependent non-networked applications Not very important in platform-dependent networked applications
E N D
Berkeley SocketsDetails for everyday use Carsten Griwodz Socket example
Data types • Basic data types • Have a certain number of bits • Not very important in platform-dependent non-networked applications • Not very important in platform-dependent networked applications • Very important in platform-independent networked applications Socket example
Data types • Basic data types • C data types char unsigned char - 8 bits short unsigned short - 16 bits int unsigned int - 32 (or 64) bits long unsigned long - 32 or 64 bits long long unsigned long long - 64 (or 128) bits • Socket API portable types size_t – 32 bits unsigned, 0 – 2^32-1 ssize_t – 32 bits signed, -2^31 – 2^31-1 Socket example
IP addresses and hostnames • IPv4 host address • When written on paper, it looks like 129.240.71.213 • ”dotted decimal notation” • Represents a 32 bit address • Binary in bits • 10000001 11110000 01000111 11010101 • Hexadecimal in bytes • 0x81 0xf0 0x47 0xd5 • One 4 byte int on x86, StrongARM, XScale, … • 0xd547f081 • One 4 byte int on PowerPC, POWER, Sparc, … • 0x81f047d5 • In network byte order • 0x81f047d5 Socket example
IP addresses and hostnames • On x86 etc. • ntohl(0x81f047d5) == 0xd547f081 • On PowerPC etc. • ntohl(0x81f047d5) == 0x81f047d5 Socket example
IP addresses and hostnames • IPv4 host address • Corresponds to one network interface card (NIC) • IPv4 network address • Looks like 129.240.69.0/24 • Refers to add addresses that that the same first 24 bits • 10000001 11110000 0100011111010101 • 129.240.69.213 is in that network Socket example
0 network host 10 network host 110 network host 1110 multicast address IP addresses and hostnames • IPv4 networks • Institutes and companies own network address ranges • e.g. 129.240.0.0/16 - UiO • e.g. 9.0.0.0/8 – IBM • Institutes and companies assign addresses to their computers • Fixed addresses • Temporary addresses Class A addresses 1.0.0.0/8 - 127.0.0.0/8 Class B addresses 128.0.0.0/16 - 191.255.0.0/16 192.0.0.0/24 - 223.255.255.0/24 Class C addresses Class D or multicast addresses 224.0.0.0 - 239.255.255.255 Socket example
IP addresses and hostnames • IPv4 networks • Institutes and companies own network address ranges • e.g. 129.240.0.0/16 - UiO • e.g. 9.0.0.0/8 – IBM • Institutes and companies assign addresses to their computers • Fixed addresses • Temporary addresses • They can also create subnets • IFI has subnets of UiO’s address space • E.g. 129.250.69.0/24 • 129.250.69.0 can’t be used for a computer, it’s the network’s address • 129.250.69.255 can’t be used for a computer, it’s an address for all computers in the network, the broadcast address Socket example
001 13 bit top level 32 bit next level 16 bit site level 64 bit interface id IP addresses and hostnames • These are many addresses • Why do we need IPv6? • Most IPv4 addresses have owners • No matter whether the addresses are needed • Most in the US, using 1% • Several in Europe • Really tight in Asia, only assigned when need is proven • IPv6 addresses • 128 bits • In text • 2FFF:80:0:0:0:0:94:1 – 8 times 16 bits • Hard to remember own address Socket example
IP addresses and hostnames • Hostnames • More exactly fully qualified host names • Look like niu.ifi.uio.no • Host niu • In subdomain ifi, Institutt for Informatik • In domain uio, Universitet i Oslo • In top level domain no, Norway • Who decided this? • .no - IANA gave it to Uninett • .uio - Uninett gave it to UiO • .ifi - USIT, UiO’s drift, gave it to IFI • niu - IFI drift gave it to the machine Socket example
Name resolution 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(port_number); • Gethostbyname • Takes a hostname • Returns information about that hostname • Including its IP address • How? Socket example
Name resolution # # list of statically known hosts # 127.0.0.1 localhost 129.27.2.1 argul.ifi.uio.no argul 129.27.2.21 fileserver.ifi.uio.no fileserver • Gethostbyname • Takes a hostname • Returns information about that hostname • Including its IP address • How? • First: • Look into /etc/hosts • But only for few, special, well-known hosts Socket example
Name resolution Root name server • Gethostbyname • Takes a hostname • Returns information about that hostname • Including its IP address • How? • Then: • Using DNS • the Domain Name System 4 2 5 3 ifi.uio.no dns.umass.edu 1 6 gaia.cs.umass.edu a121.ifi.uio.no Socket example
Name resolution #define h_addr h_addr_list[0] struct hostent { /* official hostname */ char* h_name; /* alias names of the host * entry NULL indicates end of the list */ char **h_aliases; /* host address type, e.g. AF_INET */ int h_addrtype; /* length of each address */ int h_length; /* list of addresses, primary is 0th entry * entry 0 indicates end of the list */ char** h_addr_list; }; • Gethostbyname • Takes a hostname • Returns information about that hostname • Including its IP address • Return value • Pointer tostruct hostent • Contains more than just an IP address • Other names • All addresses Socket example
Name resolution eth0 Link encap:Ethernet HWaddr 00:C0:4F:A3:0C:D3 inet addr:129.240.70.96 Bcast:129.240.71.255 Mask:255.255.248.0 UP BROADCAST NOTRAILERS RUNNING MULTICAST MTU:1500 Metric:1 RX packets:40543011 errors:65 dropped:0 overruns:203 frame:65 TX packets:9222810 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:100 RX bytes:3360933562 (3205.2 Mb) TX bytes:2321704496 (2214.1 Mb) Interrupt:19 Base address:0xfcc0 lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:26429 errors:0 dropped:0 overruns:0 frame:0 TX packets:26429 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:5877172 (5.6 Mb) TX bytes:5877172 (5.6 Mb) • Finding the own hostname • Command line • ifconfig –a (Unix) • ipconfig /a (Windows) • Gives you all IP addresses • Typically 2: • 127.0.0.1 localhost • and the actual one • Inside a program • Difficult without a connected socket • With a connected socket: • struct hostent* getsockname(int sock); • Similar to gethostbyname Socket example
Netmasks • Help your computer find the way • All computers with addresses in the same network can be reached directly • If you know your own computer’s address, e.g. 129.240.70.96 • … and the relevant bits of your network, e.g. /24 • … you know that all computers with addresses 129.240.70.? are in the same network • For each computer with another address, a member of the own network (computer or router) must be found that can send the data into the right direction • This is sometimes wrong • Understanding of network addresses becomes important • Tell your computer its network address • For computers with a fixed IP address: set up once • For computers with a dynamic address: set up together with address Socket example
Netmasks • The computer • Is not told directly that it’s on the network 129.240.70.0/24 • Instead it is told that it’s address is 129.240.70.97 • And that its netmask is 255.255.255.0 – these are 24 bits • It figures the network address out from this • In ifconfig or ipconfig • Lists hostname • E.g. 129.240.70.97 • Lists netmask • e.g. 255.255.255.0 • Or 0xffffff00 • Or the highest 24 bits set • Implies that • 129.240.70.97 • is part of the subnet 129.240.70.97/24 • which is the same as 129.240.70.0/24 • This answer from ifconfig implies also that • All computers in the net 129.240.70.0/24 are reachable directly • Without router Socket example
Binding TCP client sockets to ports int boundconnect( char* servername, int port, int ownport ) { … if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { … } bzero(&ownaddr, sizeof(ownaddr)); ownaddr.sin_family = AF_INET; ownaddr.sin_addr.s_addr = INADDR_ANY; ownaddr.sin_port = htons(ownport); if (bind(sock, (struct sockaddr *)&ownaddr, sizeof(ownaddr)) < 0) { … } if ((hostp = gethostbyname(machine)) == 0) { … } bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; memcpy(&serveraddr.sin_addr, hostp->h_addr, hostp->h_length); serveraddr.sin_port = htons(port_number); if (connect(sock, (struct sockaddr *)&serveraddr, sizeof serveraddr) < 0) { … } return sock; } • Main reasons to do this • Use a specific network card • Other potential reasons • Firewalls may restrict open ports • Server demands connection from a priviledged port • 0 – 1023 • Associate virtual circuit tags with source ports Socket example
Connecting TCP socket Client Server socket bind socket CLOSED CLOSED connect Wait 30 sec Recv ACK listen Send SYN TIME_WAIT LAST_ACK SYN_SENT LISTEN Recv SYN, Send ACK and SYN Rcvd SYN, ACK Send ACK Recv FIN, Send ACK Send FIN read write FIN_WAIT_2 ESTABLISHED CLOSE_WAIT SYN_REVD close read write Recv ACK Send FIN Recv FIN, Send ACK Recv ACK FIN_WAIT_1 ESTABLISHED Socket example
TCP Handshake Client Server CLOSED connect Send SYN SYN_SENT LISTEN Recv SYN, Send ACK and SYN Rcvd SYN, ACK Send ACK ESTABLISHED SYN_REVD Recv ACK ESTABLISHED Socket example
Connecting UDP sockets • Datagram service UDP • Usually unconnected • connect can be used • Has only local meaning • Local UDP ”remembers” a target socket • Advantage • Reading and writing is simpler • Possible to figure best packet size • Disadvantage • Can use unconnected sockets to send to several receivers • Connected sockets only to one Socket example
Reading and writing function calls • int read( int sock, void* buffer, int n) • sock must be connected • int recv( int sock, void* buffer, int n, int options ) • sock must be connected • Sometimes useful option MSG_PEEK: read packet but leave it in the queue • int recvfrom( int sock, void* buffer, int n, int options, struct sockaddr* src, int* srclen ) • Meant for unconnected sockets • If sock is connected, src is identical to sockaddr from accept Socket example
Reading and writing function calls • int write( int sock, void* buffer, int n) • sock must be connected • int send( int sock, void* buffer, int n, int options ) • sock must be connected • int sendto( int sock, void* buffer, int n, int options, struct sockaddr* dest, int destlen ) • Meant for unconnected sockets • If sock is connected, dest address must refer to the other side Socket example
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 example
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 the chat example • Wait for data from chat partner • Wait for typing of the user Socket example
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 • Non often used • Non-blocking send is finished • except_set • Hardly ever used • sendto(.,.,.,MSG_OOB) Socket example
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 example
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 example
Safe writing int safewrite(int so, char buf[], int l) { int i; if (i=write(so, buf, l)==0) { printf("Can't write to socket, connection is closed" ); exit(1); } return i; } • You never know when something strange happens on your TCP connection • Safe writing is necessary • Code from last lecture • Considers closing of the socket Socket example
Safer writing • Not all data may be sent at once • TCP takes as much as it wants to • Try to send again • If there was no error Socket example
Safer writing int safewrite( int sock, char buffer[], int len ) { int ij=0; do { i = write( sock, &buffer[j], len ); if( i == -1 ) { perror( “Error writing to socket” ); exit( 1 ); } else if( i == 0 ) { printf( “The socket has been closed, quitting\n” ); exit( 1 ); } len = len – i; j = j + i; } while( len > 0 ); return 1; } Socket example
Not all data may be sent at once TCP takes as much as it wants to Try to send again If there was no error If there was no important error Safer writing Socket example
Safer writing int safewrite( int sock, char buffer[], int len ) { int I,j=0; do { i = write( sock, &buffer[j], len ); if( i == -1 ) { switch( errno ) { case EINTR : /* do nothing, no problem */ break; default: perror( “Error writing to socket” ); exit( 1 ); } } else if( i == 0 ) { printf( “The socket has been closed, quitting\n” ); exit( 1 ); } else if( i > 0 ) { len = len – i; j = j + i; } } while( len > 0 ); return 1; } Socket example
Not all data may be sent at once TCP takes as much as it wants to Try to send again If there was no error If there was no important error You may receive a signal These are alarm signals in case of emergencies Pressing CTRL-C raises a signal SIGKILL An interrupt that ends your program if you don’t handle it Server that use TCP Get SIGPIPE often When the receiver crashes in the middle of a write Safer writing Socket example
Safer writing int main( ) { … signal( SIGPIPE, SIG_IGN ); /* I don’t want to do much */ … } int safewrite( int sock, char buffer[], int len ) { int I, j = 0; do { i = write( sock, &buffer[j], len ); if( i == -1 ) { switch( errno ) { case EINTR : /* do nothing, no problem */ break; case EPIPE : /* do nothing, will write 0 next round */ break; default: perror( “Error writing to socket” ); exit( 1 ); } } else if( i == 0 ) { printf( “The socket has been closed, quitting\n” ); exit( 1 ); } else if( i > 0 ) { len = len – i; j = j + i; } } while( len > 0 ); return 1; } Socket example
Not all data may be sent at once TCP takes as much as it wants to Try to send again If there was no error If there was no important error You may receive a signal These are alarm signals in case of emergencies Pressing CTRL-C raises a signal SIGKILL An interrupt that ends your program if you don’t handle it Server that use TCP Get SIGPIPE often When the receiver crashes in the middle of a write Slow clients block the server Important if your server has other things to do For example sending data to many clients at once Send only the data that you can send immediately Send more data when the connection is ready to take more Set the socket in non-blocking mode … … and use select Safer writing Socket example
Safer writing int main( ) { … signal( SIGPIPE, SIG_IGN ); /* I don’t want to do much */ … } int safewrite( int sock, char buffer[], int len ) { int I, j = 0; i = write( sock, &buffer[j], len ); if( i == -1 ) { switch( errno ) { case EINTR : /* do nothing, no problem */ break; case EPIPE : /* do nothing, will write 0 next round */ break; default: perror( “Error writing to socket” ); return -1; } } else if( i == 0 ) { printf( “The socket has been closed, quitting\n” ); return -1; } else if( i > 0 ) { len = len – i; j = j + i; } return i; } Socket example
Safer writing int createASocket( char machine[], int port_number ) { … sock[i] = TCPClientSocket(machine, port_number); int retval = fcntl( sock[i], F_SETFL, O_NONBLOCK); if( retval == -1 ) { perror( “Could not set socket into non-blocking mode” ); } … } void safeWriteToMany( int sock[], int nsock, char buf [], int l[]) { int i, retval, again=1, max=0; int* w; fd_set writable; w = (int*)malloc( nsock ); memset( w, 0, sizeof(int)*nsock ); while( again == 1 ) { again = 0; FD_ZERO( &writable ); for( i=0; i<nsock; i++ ) { FD_SET( sock[i], &writable ); max=MAX(sock[i],max); } retval = select( max+1, NULL, &writable, NULL, NULL ); if( retval > 0 ) { for( i=0; i<nsock; i++ ) { if( FD_ISSET( sock[i], &writable ) ) { retval = safewrite( sock[i], &buf[w[i]], l[i] ); … l[i] = l[i] – retval; /* if no error but not finished */ w[i] = w[i] + retval; if( l[i] > 0 ) again = 1; } } } } free( w ); } Socket example
Socket options • Two ways to set socket options • setsockopt( int sock, int level, int optname, void* optvalue, int optlen ) • Options for reading and writing all types of sockets • Often used insetsockopt( request_sock, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); • fcntl( int sock, int optname, long optvalue ); • Options for reading and writing all types of sockets, files, pipes, user input, graphical output • Often used in fcntl( sock[i], F_SETFL, O_NONBLOCK); Socket example
Summary • Names and addresses • IP addresses • Fully qualified hostnames • Domain Name System • How to use it • Connections in TCP and UDP • Functions • The select function call • Several functions for reading and writing • Writing really safe • To one • To many Socket example