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

Introduction To The Socket API: Tom Kelliher, CS43, Mar. 19, 1996

This document provides an introduction and overview of the socket API for creating client-server applications in C. It describes functions for socket creation (socket), binding to an address and port (bind), listening for connections (listen), accepting connections (accept), connecting to servers (connect), reading from and writing to sockets (read, write), and closing sockets (close). It also includes examples of a simple iterative server and client program that use these socket functions to exchange messages.

Uploaded by

Ranjitha_15
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
65 views

Introduction To The Socket API: Tom Kelliher, CS43, Mar. 19, 1996

This document provides an introduction and overview of the socket API for creating client-server applications in C. It describes functions for socket creation (socket), binding to an address and port (bind), listening for connections (listen), accepting connections (accept), connecting to servers (connect), reading from and writing to sockets (read, write), and closing sockets (close). It also includes examples of a simple iterative server and client program that use these socket functions to exchange messages.

Uploaded by

Ranjitha_15
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 12

Introduction to the Socket API

Tom Kelliher, CS43 ,Mar. 19, 1996 A Client-Server Dialogue

Sockets API
socket()
#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol);

Used to create an unamed socket. Must bind or connect. Returns a socket descriptor (small positive int). Returns -1 on error.
domain: type:

--- UNIX domain protocols. AF_INET --- Internet domain protocols. ...
AF_UNIX

--- TCP protocol. SOCK_DGRAM --- UDP protocol. SOCK_RAW --- IP protocol. ...
SOCK_STREAM

protocol:

set to 0.

Typical call:
int sock; if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) die();

bind()
#include <sys/types.h> #include <sys/socket.h> int bind(int sd, const struct sockaddr *name, int namelen);

Assigns a name (port, etc.) to a socket.

Returns 0 if successful, otherwise -1 and look in errno.


sd:

socket descriptor.

name:

Pointer to a struct sockaddr_in for Internet sockets. Cast to struct sockaddr *.


/* * Socket address, internet style. */ struct sockaddr_in { u_char sin_len; u_char sin_family; /* AF_INET */ u_short sin_port; /* 16 bit port number */ struct in_addr sin_addr; /* IP address */ char sin_zero[8]; };

For a server:
o o

--- desired listen port. Gt 5000. sin_addr --- another struct. Where we're willing to accept connections from.
sin_port

namelen:

sizeof name structure.

Typical call:
struct sockaddr_in server; bzero((char *) &server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(SERVER_PORT); if (bind(sock, (struct sockaddr *) &server, sizeof(server))) die();

listen()
#include <sys/types.h> #include <sys/socket.h> int listen(int sd, int backlog);

Announce willingness to accept connections to socket and a maximum queue length. Returns 0 on success, otherwise -1.

sd:

socket descriptor. max size of queue. Maximum is 5.

backlog:

Typical call:
int sock; listen(sock, 5);

accept()
#include <sys/types.h> #include <sys/socket.h> int accept(int sd, struct sockaddr *addr, int *addrlen);

Extract first connection request on queue; blocking if queue is empty. Returns -1 on error, otherwise a non-negative descriptor to use for socket I/O ( read() or write()).
sd:

socket descriptor.

addr:

Pointer to a struct sockaddr_in for Internet sockets. Cast to struct sockaddr *. sin_port --- client port. sin_addr --- client IP address. addressof sizeof addr structure.

addrlen:

Typical call:
struct sockaddr_in client; int msgsock, sock, clientLen; clientLen = sizeof(client); if ((msgsock = accept(sock, (struct sockaddr *) &client, &clientLen)) == -1) die(); else { /* Print information about the client. */ if (clientLen != sizeof(client)) die(); printf("Client IP: %s\n", inet_ntoa(client.sin_addr));

printf("Client Port: %hu\n", ntohs(client.sin_port));

connect()
#include <sys/types.h> #include <sys/socket.h> int connect(int sd, const struct sockaddr *name, int namelen);

Connect socket to another socket, opening a socket pair communication channel. Returns 0 on success, -1 otherwise. Check errno.
sd:

socket descriptor.

name:

Pointer to a struct sockaddr_in for Internet sockets. Cast to struct sockaddr *. sin_port --- server port. sin_addr --- server IP address. sizeof name structure.

namelen:

Will automatically do a bind and assign an ephemeral port. Use getsockname() to discover the port number. Typical call:
struct sockaddr_in server; struct hostent* hp; bzero((char *) &server, sizeof(server)); server.sin_family = AF_INET; if ((hp = gethostbyname(argv[1])) == NULL) { sprintf(buf, "%s: unknown host\n", argv[1]); die(buf); } bcopy(hp->h_addr, &server.sin_addr, hp->h_length); server.sin_port = htons((u_short) SERVER_PORT); /* Try to connect */ if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) pdie("Connecting stream socket"); /* Determine what port client's using. */ clientLen = sizeof(client); if (getsockname(sock, (struct sockaddr *) &client, &clientLen)) pdie("Getting socket name");

if (clientLen != sizeof(client)) die("getsockname() overwrote name structure"); printf("Client socket has port %hu\n", ntohs(client.sin_port));

read()
#include <unistd.h> ssize_t read(int sd, void* buf, size_t nbytes);

Read at most nbytes bytes into buf from sd. Returns -1 on error, 0 on EOF (connection closed), or the actual number of bytes read.
sd:

socket descriptor. addressof char buffer. sizeof buf.

buf:

nbytes:

Typical call:
char buf[BUFFER_SIZE]; int rval, msgsock; bzero(buf, BUFFER_SIZE); if ((rval = read(msgsock, buf, BUFFER_SIZE)) < 0) die();

write()
#include <unistd.h> ssize_t write(int sd, const void *buf, size_t nbytes);

Attempts to write nbytes from buf to sd. Returns -1 on error or the number of bytes actually written. Arguments similar to read().

close()
#include <unistd.h>

int close(int sd);

Close socket descriptor sd. Returns -1 on failure, otherwise 0.

Byte Ordering Calls


#include <sys/param.h> u_long u_short u_long u_short htonl(u_long hostlong); htons(u_short hostshort); ntohl(u_long netlong); ntohs(u_short netshort);

Convert 16- and 32-bit integers between native format (host) and network format.
#include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> unsigned long inet_addr(const char *ip); char* inet_ntoa(struct in_addr in); inet_addr()

converts a char string IP address to its 32-bit network byte-order integer

equivalent.
inet_ntoa

does the opposite.

Example Server Program


/********************************************************************** * server.c --- Demonstrate a simple iterative server. * Tom Kelliher * * This program demonstrates a simple iterative server. The server * opens a TCP connection on port SERVER_PORT and begins accepting * connections from anywhere. It sits in an endless loop, so one must * send an INTR to terminate it. * * The server reads a message from the client, printing it to stdout. * Then, the server sends a simple message back to the client. **********************************************************************/ #include #include #include #include #include <sys/types.h> <sys/socket.h> <netinet/in.h> <netdb.h> <stdio.h>

#include <stdlib.h> #define #define #define #define DATA "Danger Will Roger . . ." TRUE 1 SERVER_PORT 5001 BUFFER_SIZE 1024

/* prototypes */ void die(const char *); void pdie(const char *); /********************************************************************** * main **********************************************************************/ int main(void) { int sock; /* fd for main socket */ int msgsock; /* fd from accept return */ struct sockaddr_in server; /* socket struct for server connection */ struct sockaddr_in client; /* socket struct for client connection */ int clientLen; /* returned length of client from accept() */ int rval; /* return value from read() */ char buf[BUFFER_SIZE]; /* receive buffer */ /* Open a socket, not bound yet. Type is Internet TCP. */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) pdie("Opening stream socket"); /* Prepare to bind. Permit Internet connections from any client to our SERVER_PORT. */ bzero((char *) &server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(SERVER_PORT); if (bind(sock, (struct sockaddr *) &server, sizeof(server))) pdie("Binding stream socket"); printf("Socket has port %hu\n", ntohs(server.sin_port)); /* Set the listen queue to 5, the maximum. */ listen(sock, 5); /* Loop, waiting for client connections. */ /* This is an interactive server. */ while (TRUE) { clientLen = sizeof(client); if ((msgsock = accept(sock, (struct sockaddr *) &client, &clientLen)) == -1) pdie("Accept"); else {

/* Print information about the client. */ if (clientLen != sizeof(client)) pdie("Accept overwrote sockaddr structure."); printf("Client IP: %s\n", inet_ntoa(client.sin_addr)); printf("Client Port: %hu\n", ntohs(client.sin_port)); do { /* Read from client until it's closed the connection. */ /* Prepare read buffer and read. */ bzero(buf, sizeof(buf)); if ((rval = read(msgsock, buf, BUFFER_SIZE)) < 0) pdie("Reading stream message"); if (rval == 0) /* Client has closed the connection */ fprintf(stderr, "Ending connection\n"); else printf("S: %s\n", buf); /* Write back to client. */ if (write(msgsock, DATA, sizeof(DATA)) < 0) pdie("Writing on stream socket"); } } exit(0); } /********************************************************************** * pdie --- Call perror() to figure out what's going on and die. **********************************************************************/ void pdie(const char *mesg) { perror(mesg); exit(1); } /********************************************************************** * die --- Print a message and die. **********************************************************************/ void die(const char *mesg) { fputs(mesg, stderr); fputc('\n', stderr); exit(1); } } while (rval != 0); /* else */

close(msgsock);

Example Client Program


/********************************************************************** * client.c --- Demonstrate a simple client. * Tom Kelliher * * This program will connect to a simple iterative server and exchange * messages. The single command line argument is the server's hostname. * The server is expected to be accepting connection requests from * SERVER_PORT. * * The same message is sent three times over separate connections, * demonstrating that different ephemeral ports are used for each * connection. **********************************************************************/ #include #include #include #include #include #include <sys/types.h> <sys/socket.h> <netinet/in.h> <netdb.h> <stdio.h> <stdlib.h>

#define DATA "The sea is calm tonight, the tide is full . . ." #define SERVER_PORT 5001 #define BUFFER_SIZE 1024 /* prototypes */ void die(const char *); void pdie(const char *); /********************************************************************** * main **********************************************************************/ int main(int argc, char *argv[]) { int sock; /* fd for socket connection */ struct sockaddr_in server; /* Socket info. for server */ struct sockaddr_in client; /* Socket info. about us */ int clientLen; /* Length of client socket struct. */ struct hostent *hp; /* Return value from gethostbyname() */ char buf[BUFFER_SIZE]; /* Received data buffer */ int i; /* loop counter */ if (argc != 2) die("Usage: client hostname"); /* Open 3 sockets and send same message each time. */ for (i = 0; i < 3; ++i)

{ /* Open a socket --- not bound yet. */ /* Internet TCP type. */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) pdie("Opening stream socket"); /* Prepare to connect to server. */ bzero((char *) &server, sizeof(server)); server.sin_family = AF_INET; if ((hp = gethostbyname(argv[1])) == NULL) { sprintf(buf, "%s: unknown host\n", argv[1]); die(buf); } bcopy(hp->h_addr, &server.sin_addr, hp->h_length); server.sin_port = htons((u_short) SERVER_PORT); /* Try to connect */ if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) pdie("Connecting stream socket"); /* Determine what port client's using. */ clientLen = sizeof(client); if (getsockname(sock, (struct sockaddr *) &client, &clientLen)) pdie("Getting socket name"); if (clientLen != sizeof(client)) die("getsockname() overwrote name structure"); printf("Client socket has port %hu\n", ntohs(client.sin_port)); /* Write out message. */ if (write(sock, DATA, sizeof(DATA)) < 0) pdie("Writing on stream socket"); /* Prepare our buffer for a read and then read. */ bzero(buf, sizeof(buf)); if (read(sock, buf, BUFFER_SIZE) < 0) pdie("Reading stream message"); printf("C: %s\n", buf); /* Close this connection. */ close(sock); } exit(0); } /********************************************************************** * pdie --- Call perror() to figure out what's going on and die. **********************************************************************/ void pdie(const char *mesg) { perror(mesg);

exit(1); } /********************************************************************** * die --- Print a message and die. **********************************************************************/ void die(const char *mesg) { fputs(mesg, stderr); fputc('\n', stderr); exit(1); }

Thomas P. Kelliher Mon Mar 18 22:35:52 EST 1996 Tom Kelliher

You might also like