0% found this document useful (0 votes)
56 views

Socket Programming in C: Server and Client

The document discusses socket programming in C. It defines key concepts like sockets, port numbers, and Internet addressing. Sockets allow processes to communicate over a network using common APIs. Servers typically listen on well-known ports while clients use dynamic ports assigned by the kernel. The document also covers byte ordering issues and functions for converting between host and network byte order. It provides examples of creating TCP sockets and binding sockets to ports to allow clients to connect to servers.

Uploaded by

Munti Das
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
56 views

Socket Programming in C: Server and Client

The document discusses socket programming in C. It defines key concepts like sockets, port numbers, and Internet addressing. Sockets allow processes to communicate over a network using common APIs. Servers typically listen on well-known ports while clients use dynamic ports assigned by the kernel. The document also covers byte ordering issues and functions for converting between host and network byte order. It provides examples of creating TCP sockets and binding sockets to ports to allow clients to connect to servers.

Uploaded by

Munti Das
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

22-Sep-17

Server and Client


Server and Client exchange messages over the
network through a common Socket API

Clients
Server user
ports space

Socket programming in C
TCP/UDP TCP/UDP
Socket API kernel
space

IP IP

Ethernet Adapter Ethernet Adapter hardware

Concept of Port Numbers Names and Addresses


–Port numbers are used to identify
“entities” on a host (16 bit) NTP Web • Each attachment point on Internet is given
–Port numbers can be daemon server unique address
• Well-known (port 0-1023)
port 123
• Registered (port 1024 – 49151) port 80 – Based on location within network – like phone
• Dynamic or private (port 49152-65535) numbers
–Servers/daemons usually use well- TCP/UDP
known ports • Humans prefer to deal with names not addresses
• Any client can identify the server/service IP – DNS provides mapping of name to address
• HTTP = 80, FTP = 21, Telnet = 23, ...
• /etc/services defines well-known ports – Name based on administrative ownership of host
Ethernet Adapter
–Clients usually use dynamic ports
• Assigned by the kernel at run time

1
22-Sep-17

Internet Addressing Data


Byte Ordering
Structure
#include <netinet/in.h> union {
u_int32_t addr; /* unsigned long int, 4
/* Internet address structure */ bytes address */
struct in_addr { unsigned char c[4];
u_long s_addr; /* 32-bit IPv4 address */ } un;
}; /* network byte ordered */ /* 128.2.194.95 */
un.addr = 0x8002c25f;
/* Socket address, Internet style. */ /* un.c[0] = ? */ c[0] c[1] c[2] c[3]
struct sockaddr_in {
u_char sin_family; /* Address Family */
u_short sin_port; /* UDP or TCP Port# */
• Big Endian 128 2 194 95
/* network byte ordered */ – Sun Solaris, PowerPC, ...
struct in_addr sin_addr; /* Internet Address */ 95 194 2 128
• Little Endian
char sin_zero[8]; /* unused */
}; – i386, alpha, ...
• Network byte order = Big Endian
• sin_family = AF_INET selects Internet address family

• Byte Order
– Different computers may have different internal representation of 16 / 32-
bit integer (called host byte order).
Byte Ordering Functions
– Examples • Converts between host byte order and network byte
• Big-Endian byte order (e.g., used by Motorola 68000): order
– ‘h’ = host byte order
– ‘n’ = network byte order
– ‘l’ = long (4 bytes), converts IP addresses
– ‘s’ = short (2 bytes), converts port numbers
• Little-Endian byte order (e.g., used by Intel 80x86): #include <netinet/in.h>

unsigned long int htonl(unsigned long int hostlong);


unsigned short int htons(unsigned short int hostshort);
unsigned long int ntohl(unsigned long int netlong);
unsigned short int ntohs(unsigned short int netshort);

2
22-Sep-17

What is a Socket? TCP Server


• A socket is a file descriptor that lets an application read/write data from/to the
network • For example: web server
int fd; /* socket descriptor */ Web Server
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) }
perror(“socket”); Port 80 • What does a web server
exit(1); need to do so that a web
} client can connect to it?
TCP
• socket returns an integer (socket descriptor)
– fd < 0 indicates that an error occurred
IP
– socket descriptors are similar to file descriptors

• AF_INET: associates a socket with the Internet protocol family Ethernet Adapter
• SOCK_STREAM: selects the TCP protocol
• SOCK_DGRAM: selects the UDP protocol

Socket I/O: socket() Socket I/O: bind()


• Since web traffic uses TCP, the web server must create a socket of type
SOCK_STREAM • A socket can be bound to a port
int fd; /* socket descriptor */
int fd; /* socket descriptor */ struct sockaddr_in srv; /* used by bind() */

/* create the socket */


if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror(“socket”); srv.sin_family = AF_INET; /* use the Internet addr family */
exit(1);
srv.sin_port = htons(80); /* bind socket ‘fd’ to port 80*/
}
/* bind: a client may connect to any of server addresses */
• socket returns an integer (socket descriptor) srv.sin_addr.s_addr = htonl(INADDR_ANY);
– fd < 0 indicates that an error occurred
if(bind(fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) {
• AF_INET associates a socket with the Internet protocol family perror("bind"); exit(1);
• SOCK_STREAM selects the TCP protocol }

• Still not quite ready to communicate with a client...

3
22-Sep-17

Socket I/O: listen() Socket I/O: accept()


• listen indicates that the server will accept a connection • accept blocks waiting for a connection
int fd; /* socket descriptor */
int fd; /* socket descriptor */ struct sockaddr_in srv; /* used by bind() */
struct sockaddr_in srv; /* used by bind() */ struct sockaddr_in cli; /* client’s add used by accept() */
int newfd; /* returned by accept() */
/* 1) create the socket */ int cli_len = sizeof(cli); /* used by accept() */
/* 2) bind the socket to a port */
/* 1) create the socket */
/* 2) bind the socket to a port */
if(listen(fd, 5) < 0) {
/* 3) listen on the socket */
perror(“listen”);
exit(1); newfd = accept(fd, (struct sockaddr*) &cli, &cli_len);
} if(newfd < 0) {
perror("accept"); exit(1);
}
• Still not quite ready to communicate with a client... • accept returns a new socket (newfd) with the same properties as the original
socket (fd)
– newfd < 0 indicates that an error occurred

Socket I/O: accept() continued... Socket I/O: read()


struct sockaddr_in cli; /* used by accept() */ • read can be used with a socket
int newfd; /* returned by accept() */
int cli_len = sizeof(cli); /* used by accept() */ • read blocks waiting for data from the client but does not
guarantee that sizeof(buf) is read
newfd = accept(fd, (struct sockaddr*) &cli, &cli_len);
if(newfd < 0) { int fd; /* socket descriptor */
perror("accept"); char buf[512]; /* used by read() */
int nbytes; /* used by read() */
exit(1);
}
/* 1) create the socket */
• How does the server know which client it is? /* 2) bind the socket to a port */
/* 3) listen on the socket */
– cli.sin_addr.s_addr contains the client’s IP address /* 4) accept the incoming connection */
/* 5) Create a child process to attend the connection */
– cli.sin_port contains the client’s port number /* Child will close fd, and continue communication with client */
/* parent will close newfd, and continue with accepting connection*/
• Now the server can exchange data with the client by using
read and write on the descriptor newfd. if((nbytes = read(newfd, buf, sizeof(buf))) < 0) {
perror(“read”); exit(1);
• Why does accept need to return a new descriptor? }

4
22-Sep-17

Dealing with IP Addresses


TCP Client
• IP Addresses are commonly written as strings (“128.2.35.50”), but programs
• For example: web client deal with IP addresses as integers.
2 Web Clients
Converting strings to numerical address:
• How does a web client struct sockaddr_in srv;
connect to a web server?
srv.sin_addr.s_addr = inet_addr(“128.2.35.50”);
if(srv.sin_addr.s_addr == (in_addr_t) -1) {
TCP fprintf(stderr, "inet_addr failed!\n"); exit(1);
}

Converting a numerical address to a string:


IP
struct sockaddr_in srv;
char *t = inet_ntoa(srv.sin_addr);
Ethernet Adapter if(t == 0) {
fprintf(stderr, “inet_ntoa failed!\n”); exit(1);
}

Translating Names to Addresses Socket I/O: connect()


• Gethostbyname provides interface to DNS • connect allows a client to connect to a server...
• Additional useful calls int fd; /* socket descriptor */
struct sockaddr_in srv; /* used by connect() */
– Gethostbyaddr – returns hostent given sockaddr_in
– Getservbyname /* create the socket */

• Used to get service description (typically port number) /* connect: use the Internet address family */
• Returns servent based on name srv.sin_family = AF_INET;

/* connect: socket ‘fd’ to port 80 */


#include <netdb.h> srv.sin_port = htons(80);

struct hostent *hp; /*ptr to host info for remote*/ /* connect: connect to IP Address “128.2.35.50” */
struct sockaddr_in peeraddr; srv.sin_addr.s_addr = inet_addr(“128.2.35.50”);
char *name = “www.tezu.ernet.in”;
if(connect(fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) {
peeraddr.sin_family = AF_INET; perror(”connect"); exit(1);
hp = gethostbyname(name) }
peeraddr.sin_addr.s_addr = ((struct in_addr*)(hp->h_addr))->s_addr;

5
22-Sep-17

Socket I/O: write() Review: TCP Client-Server


• write can be used with a socket Interaction TCP Server
socket()
int fd; /* socket descriptor */
struct sockaddr_in srv; /* used by connect() */ bind()
char buf[512]; /* used by write() */
TCP Client listen()
int nbytes; /* used by write() */
socket() accept()
/* 1) create the socket */ connection establishment
/* 2) connect() to the server */ connect()

data request read()


/* Example: A client could “write” a request to a server write()
*/
if((nbytes = write(fd, buf, sizeof(buf))) < 0) { data reply write()
perror(“write”); read()
exit(1);
} end-of-file notification read()
close()
close()
from UNIX Network Programming by Stevens

Example: C client (TCP)


Socket programming with TCP
/* client.c */
Client must contact server void main(int argc, char *argv[])
• When contacted by client, {
• server process must first be
server TCP creates new struct sockaddr_in sad; /* structure to hold an IP address */
running int clientSocket; /* socket descriptor */
socket for server process to
• server must have created socket struct hostent *ptrh; /* pointer to a host table entry */
communicate with client
(door) that welcomes client’s char Sentence[128]; Create client socket,
– allows server to talk
contact char modifiedSentence[128]; connect to server
with multiple clients
Client contacts server by: – source port numbers host = argv[1]; port = atoi(argv[2]);
• creating client-local TCP socket used to distinguish clientSocket = socket(PF_INET, SOCK_STREAM, 0);
• specifying IP address, port clients. memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
application viewpoint sad.sin_family = AF_INET; /* set family to Internet */
number of server process sad.sin_port = htons((u_short)port);
• When client creates socket: TCP provides reliable, in-order ptrh = gethostbyname(host); /* Convert host name to IP address */
transfer of bytes (“pipe”) memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length); connect(clientSocket,
client TCP establishes between client and server (struct sockaddr *)&sad, sizeof(sad));
connection to server TCP

6
22-Sep-17

Example: C server (TCP)


Example: C client (TCP), cont.
/* server.c */
Get void main(int argc, char *argv[])
input stream gets(Sentence); {
from user struct sockaddr_in sad; /* structure to hold an IP address */
struct sockaddr_in cad;
int welcomeSocket, connectionSocket; /* socket descriptor */
Send line n=write(clientSocket, Sentence, strlen(Sentence)+1); struct hostent *ptrh; /* pointer to a host table entry */
to server
char clientSentence[128]; Create welcoming socket at port
char capitalizedSentence[128]; &
Read line n=read(clientSocket, modifiedSentence, sizeof(modifiedSentence)); Bind a local address
from server port = atoi(argv[1]);

printf("FROM SERVER: %s\n”,modifiedSentence); welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);


memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
Close close(clientSocket); sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */
connection sad.sin_port = htons((u_short)port);/* set the port number */
} bind(welcomeSocket, (struct sockaddr *)&sad, sizeof(sad));

Example: C server (TCP), cont Socket programming with UDP


/* Specify the maximum number of clients that can be queued */
listen(welcomeSocket, 10)
Wait, on welcoming socket
while(1) { for contact by a client UDP: no “connection”
between client and server
connectionSocket=accept(welcomeSocket, (struct sockaddr *)&cad, &alen);
• no handshaking
n=read(connectionSocket, clientSentence, sizeof(clientSentence)); application viewpoint
• sender explicitly attaches
UDP provides unreliable transfer
/* capitalize Sentence and store the result in capitalizedSentence*/ IP address and port of
of groups of bytes (“datagrams”)
destination to each packet between client and server
n=write(connectionSocket, capitalizedSentence, strlen(capitalizedSentence)+1); • server must extract IP
address, port of sender
close(connectionSocket); from received packet
} Write out the result to socket
}
UDP: transmitted data may
End of while loop,
loop back and wait for be received out of order,
another client connection or lost

7
22-Sep-17

Example: C client (UDP)


Client/server socket interaction: UDP /* client.c */
void main(int argc, char *argv[])
Server (running on hostid) Client {
struct sockaddr_in sad; /* structure to hold an IP address */
create socket, int clientSocket; /* socket descriptor */
create socket,
port=x, for clientSocket = struct hostent *ptrh; /* pointer to a host table entry */
incoming request: DatagramSocket()
serverSocket =
DatagramSocket() char Sentence[128];
Create client socket,
Create, address (hostid, port=x, char modifiedSentence[128];
NO connection to server
send datagram request
read request from using clientSocket host = argv[1]; port = atoi(argv[2]);
serverSocket
clientSocket = socket(PF_INET, SOCK_DGRAM, 0);
write reply to
serverSocket
specifying client read reply from /* determine the server's address */
host address, clientSocket memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
port number close sad.sin_family = AF_INET; /* set family to Internet */
clientSocket sad.sin_port = htons((u_short)port);
ptrh = gethostbyname(host); /* Convert host name to IP address */
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);

Example: C server (UDP)


Example: C client (UDP), cont.
/* server.c */
Get void main(int argc, char *argv[])
input stream gets(Sentence); {
from user struct sockaddr_in sad; /* structure to hold an IP address */
struct sockaddr_in cad;
addr_len =sizeof(struct sockaddr); int serverSocket; /* socket descriptor */
Send line
n=sendto(clientSocket, Sentence, strlen(Sentence)+1, struct hostent *ptrh; /* pointer to a host table entry */
to server
(struct sockaddr *) &sad, addr_len);
char clientSentence[128]; Create welcoming socket at port
char capitalizedSentence[128]; &
Bind a local address
n=recvfrom(clientSocket, modifiedSentence, sizeof(modifiedSentence).
Read line port = atoi(argv[1]);
(struct sockaddr *) &sad, &addr_len);
from server
serverSocket = socket(PF_INET, SOCK_DGRAM, 0);
printf("FROM SERVER: %s\n”,modifiedSentence); memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
Close close(clientSocket); sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address */
connection } sad.sin_port = htons((u_short)port);/* set the port number */
bind(serverSocket, (struct sockaddr *)&sad, sizeof(sad));

8
22-Sep-17

Example: C server (UDP), cont A Few Programming Notes:


while(1) { Receive messages from clients
Representing Packets
n=recvfrom(serverSocket, clientSentence, sizeof(clientSentence), 0
(struct sockaddr *) &cad, &addr_len ); 0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
/* capitalize Sentence and store the result in capitalizedSentence*/ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length | Checksum |
n=sendto(connectionSocket, capitalizedSentence, strlen(capitalizedSentence)+1,0
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
(struct sockaddr *) &cad, &addr_len); | Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
close(connectionSocket);
} Write out the result to socket Type: 4-byte integer
} Length: 2-byte integer
Checksum: 2-byte integer
End of while loop,
Address: 4-byte IP address
loop back and wait for
another client connection

A Few Programming Notes:


Building a Packet in a Buffer Socket Programming References
struct packet {
u_int32_t type;
u_int16_t length;
• Man page
u_int16_t checksum; – usage: man <function name>
u_int32_t address;
}; • Textbook
/* ================================================== */ – Stevens, Unix Network Programming, PHI
char buf[1024];
struct packet *pkt;

pkt = (struct packet*) buf;


pkt->type = htonl(1);
pkt->length = htons(2);
pkt->checksum = htons(3);
pkt->address = htonl(4);

You might also like