Sie sind auf Seite 1von 49

EPL375: Advanced Networks TCP/IP Socket Programming in C

By: Dr. Vasos Vassiliou Spring 2009

University of Cyprus Department of Computer Science

Overview
Introduction

TCP/IP Basic
UNIX/C Sockets
UDP Sockets TCP Sockets Utility Functions

Other Socket API

Summary

Internet Protocol (IP)


Datagram (packet) protocol Best-effort service
Loss Reordering Duplication Delay

Host-to-host delivery (not application-to-application)

IP Address
32-bit identifier Identifies a host interface (not a host)

Transport Protocols
Best-effort is not sufficient !!!
Add services on top of IP User Datagram Protocol (UDP)
Data checksum Best-effort

Transmission Control Protocol (TCP)


Data checksum Reliable byte-stream delivery Flow and congestion control

Ports
Identifying the ultimate destination
IP addresses identify hosts Host has many applications Ports (16-bit identifier)
Application Port WWW 80 E-mail 25 Telnet 23

194.42.16.25

TCP/IP Byte Transport


TCP/IP protocols transports bytes
Application
byte stream Here are some bytes. I dont know what they mean.

Application
byte stream Ill pass these to the app. It knows what to do.

TCP/IP

TCP/IP

Application protocol provides semantics

Socket
How does one speak TCP/IP?
Sockets provides interface to TCP/IP Generic interface for many protocols

Socket Types

Socket
Identified by protocol and local/remote address/port Applications may refer to many sockets Socket abstraction
Berkeley Sockets (traditional)
Generic
multiple families address representation independence)

Uses existing I/O programming interface as much as possible

Sockets work with Unix I/O services just like files, pipes Sockets have special needs:
establishing a connection specifying communication endpoint addresses

TCP/IP Sockets
mySock = socket(family, type, protocol); TCP/IP-specific sockets
Family TCP PF_INET UDP SOCK_DGRAM IPPROTO_UDP Type SOCK_STREAM Protocol IPPROTO_TCP

Socket reference
File (socket) descriptor in UNIX Socket handle in WinSock

Generic

struct sockaddr { unsigned short sa_family; char sa_data[14]; }; struct sockaddr_in { unsigned short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; struct in_addr { unsigned long s_addr; };

/* Address family (e.g., AF_INET) */ /* Protocol-specific address information */

IP Specific

/* Internet protocol (AF_INET) */ /* Port (16-bits) */ /* Internet address (32-bits) */ /* Not used */

/* Internet address (32-bits) */

sockaddr

Family 2 bytes 2 bytes Port 4 bytes Internet address

Blob 8 bytes

sockaddr_in

Family

Not used

Clients and Servers


Client: Initiates the connection
Client: Bob Hi. Im Bob. Hi, Bob. Im Jane Nice to meet you, Jane. Server: Jane

Server: Passively waits to respond

Functions needed
Specify local and remote communication endpoints Initiate a connection Wait for incoming connection Send and receive data Terminate a connection gracefully Error handling

TCP Client/Server Interaction


Server starts by getting ready to receive client connections

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Assign a port to socket Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

Creating a Socket
int socket(int family, int type, int proto)
system call returns a socket descriptor(small integer); -1 on error allocates resources needed for a communication endpoint; does not deal with endpoint addressing

family specifies the protocol family


AF_INET for TCP/IP

type specifies the type of service(communication)


SOCK_STREAM, SOCK_DGRAM

protocol specifies the specific protocol


usually 0 which means the default

Declaration for socket function

Specifying an Endpoint Address


Remember that the sockets API is generic There must be a generic way to specify endpoint addresses TCP/IP requires an IP address and a port number for each endpoint address. Other protocol suites(families) may use other schemes. Generic socket addresses(The C function that make up the sockets API expect structures of type sockaddr.) :
struct sockaddr { unsigned short sa_family; //specifies the address type char sa_data[14]; //specifies the address value };

Assigning an address to a socket


int bind(int socket, (struct sockaddr *) address, int address_length);
The bind() system call is used to assign an address to an existing socket. bind returns 0 if successful or -1 on error

Example:
struct sockaddr_in sin; int s; s = socket(AF_INET, SOCK_DGRAM, 0); sin.sin_family = AF_INET; sin.sin_port = htons(9999); sin.sin_addr.s_addr = INADDR_ANY; bind(s, (struct sockaddr *)&sin, sizeof(sin));

listen() connect() -- TCP Sockets


int listen(int socket, int qlength)
allows servers to prepare a socket for incoming connections puts the socket in a passive mode ready to accept connections informs the OS that the protocol software should enqueue multiple simultaneous requests that arrive at the socket applies only to sockets that have selected reliable stream delivery service

int connect(int, struct sockaddr *dest_addr, int);


binds a permanent destination to a socket changes the socket state from unconnected state to connected state The semantics of connect depend on the underlaying protocol
TCP connection (AF_INET, reliabe stream delivery service) just store the destination address locally (connectionless)

accept() -- TCP Sockets


int accept(int, struct sockaddr * addr, int * addrlen)
needs to wait for a connection blocks until a connection request arrives addrlen is a pointer to an integer;
when a request arrives , the system fills in argument addr with the address of the client that has placed the request and sets addrlen to the length of the address. system creates a new socket, returns the new socket descriptor

send() and recv() -- TCP Sockets


int send(int s, const char *msg, int len, int flags)
connected socket argument flags controls the transmission.
allows the sender to specify that the message should be sent out-of- band messages correspond to TCPs urgent data allows the caller to request that the message be sent without using local routine tables (take control of routine)

int recv(int s, char *buf, int len, int flags)


connected socket argument flags allow the caller to control the reception
look ahead by extracting a copy of the next incoming message without removing the message from the socket

close() and shutdown()


close(int socket)
For UDP sockets, this will release the ownership on the local port that is bound to this socket For TCP, this will initiate a two-way shutdown between both hosts before giving up port ownership.

shutdown(int socket, int how)


f the how field is 0, this will disallow further reading (recv) from the socket. If the how field is 1, subsequent writes (send) will be disallowed. The socket will still need to be passed to close.

Relationship Between Sockets and File Descriptors


Socket handles are integer values. In UNIX, socket handles can be passed to most of the low-level POSIX I/O functions.
read(s, buffer, buff_length); //s could be a file descriptor too write(s, buffer, buff_length) ;

Calling read on an open socket is equivalent to recv


if the socket is UDP, then information about the sender of the datagram will not be returned

Similarly the write function call is equivalent to send


UDP sockets may call connect to use send and write

use the socket library functions instead of the file I/O equivalents.

Socket interface for Connectionless Iterative Server

TCP Client/Server Interaction


/* Create socket for incoming connections */ if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) DieWithError("socket() failed");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


echoServAddr.sin_family = AF_INET; /* Internet address family */ echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);/* Any incoming interface */ echoServAddr.sin_port = htons(echoServPort); /* Local port */ if (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) DieWithError("bind() failed");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


/* Mark the socket so it will listen for incoming connections */ if (listen(servSock, MAXPENDING) < 0) DieWithError("listen() failed");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


for (;;) /* Run forever */ { clntLen = sizeof(echoClntAddr); if ((clntSock=accept(servSock,(struct sockaddr *)&echoClntAddr,&clntLen)) < 0) DieWithError("accept() failed");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


Server is now blocked waiting for connection from a client Later, a client decides to talk to the server
Client Create a TCP socket Establish connection Communicate Close the connection Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

1. 2. 3. 4.

1. 2. 3. 4.

TCP Client/Server Interaction


/* Create a reliable, stream socket using TCP */ if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) DieWithError("socket() failed");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


echoServAddr.sin_family = AF_INET; /* Internet address family */ echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */ echoServAddr.sin_port = htons(echoServPort); /* Server port */ if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0) DieWithError("connect() failed");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


if ((clntSock=accept(servSock,(struct sockaddr *)&echoClntAddr,&clntLen)) < 0) DieWithError("accept() failed");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


echoStringLen = strlen(echoString); /* Determine input length */ /* Send the string to the server */ if (send(sock, echoString, echoStringLen, 0) != echoStringLen) DieWithError("send() sent a different number of bytes than expected");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


/* Receive message from client */ if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0) DieWithError("recv() failed");

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Client/Server Interaction


close(sock); close(clntSocket)

1. 2. 3. 4.

Client Create a TCP socket Establish connection Communicate Close the connection

1. 2. 3. 4.

Server Create a TCP socket Bind socket to a port Set socket to listen Repeatedly: a. Accept new connection b. Communicate c. Close the connection

TCP Tidbits

Client must know the servers address and port Server only needs to know its own port No correlation between send() and recv() Client
send(Hello Bob)

Server
recv() -> Hello recv() -> Bob send(Hi ) send(Jane)

recv() -> Hi Jane

Closing a Connection

close() used to delimit communication Analogous to EOF

Echo Client
send(string)

Echo Server

while (not received entire string) recv(buffer) print(buffer) close(socket)

recv(buffer) while(client has not closed connection) send(buffer) recv(buffer)

close(client socket)

Byte-order Transformations
Byte ordering is a function of machine architecture
Intel: little-endian Sparc, PowerPC: big-endian Network order: big-endian

The byte order for the TCP/IP protocol suite is big endian.

Big-endian byte order

Little-endian byte order

Network Byte Order Functions

Network Byte Order Functions


Functions:
u_long m =ntohl(u_long m)
network-to-host byte order, 32 bit

u_long m =htonl(u_long m)
host-to-network byte order, 32 bit

ntohs(),htons()
short (16 bit)

Example:
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(9999); sin.sin_addr.s_addr = inet_addr;

Address transformation

Address transformation
unsigned int inet_addr(char *str)
str represents an IP address(dotted-quad notation); inet_addr will return it's equivalent 32-bit value in network byte order. This value can be passed into the sin_addr.s_addr field of a socketaddr_in structure -1 is returned if the string can not be interpreted

char *inet_ntoa(struct in_addr ip)


Converts the 32-bit value which is assumed to be in network byte order and contained in ip to a string The pointer returned by inet_ntoa contains this string. However, subsequent calls to inet_ntoa will always return the same pointer, so copying the string to another buffer is recommended before calling again.

Obtaining Information About Hosts, etc.


struct hostent *hptr; /*includes host address in binary*/ hptr=gethostbyname(char *name); Ex.:gethostbyname(www.csc.ncsu.edu);

Struct hostent *hptr; hptr=gethostbyaddr(char *addr,int addrlen, int addrtype); Ex: gethostbyaddr(&addr, 4, AF_INET);

Obtaining Information About Hosts, etc.


int inet_addr(char *dotdecimal); Ex.: sin_addr = inet_addr(152.14.51.129); struct servent *sptr; /* includes port and protocol */ sptr=getservbyname(char *name, char *proto); Ex.: getservbyname(smtp, tcp); struct protoent *pptr; /* includes protocol number */ pptr=getprotobyname(char *name); Ex.: getprotobyname(tcp);

Others
Include files
#include <sys/types.h>; #include <sys/socket.h>; #include <netinet/in.h>; #include <arpa/inet.h>; #include <netdb.h>; #include <unistd.h>; #include <signal.h>; #include <stdio.h>; #include <fcntl.h>; #include <errno.h; #include <sys/time.h>; #include <stdlib.h>; #include <memory.h>;

Compiling and Linking


Under most versions of UNIX (Linux, BSD, SunOS, IRIX) compiling is done as usual:
gcc my_socket_program.c -o my_socket_program

Solaris:
cc my_socket_program.c -o my_socket_program -lsocket -lnsl

Programming tips
always check the return value for each function call consult the UNIX on-line manual pages ("man") for a complete description

Summary
TCP/IP basic
UNIX/C Sockets
socket() ; bind() ; connect() ; listen() ; accept() ; sendto() ; recvfrom(); send() ; recv() ; read() ; write(); some utility functions

Das könnte Ihnen auch gefallen