Uploaded by Nirmala Ranganathan

Network Programming Materials

advertisement
MC7404 NETWORK PROGRAMMING
UNIT – I
Overview of UNIX OS - Environment of a UNIX process - Process control –
Process relationships , Signals – Interprocess Communication- overview of
TCP/IP protocols
UNIX is a computer operating system.
OPERATING SYSTEM
An operating system is the program that controls all the other parts of a
computer system, both the hardware and the software.
It allocates the computer's resources and schedules tasks.
It helps to use the facilities provided by the system
Every computer requires an operating system.
How UNIX was developed
Back to 60’s
There were NO personal computers
There were different mainframe computers, each with its own operating
system
Computers were NOT networked; data transfer was via magnetic tape.
Often computers from the same manufacturer could not talk to each other
It was difficult to get one program created on one system to work on another
system, and it was even difficult to transfer data output by one system into
another system.
There was no C programming language, or for that matter no standardized
programming language at all
Programming was frequently done by submitting a program via punch cards
and the computer delivered a printed answer
More and more ―dumb terminals‖ were hooked up to a mainframe (text-based
only) which required a multi-user, multi-tasking operating system – many
were not.
History of UNIX
Bell Laboratories (formerly Bell Telephone Labs, then AT&T Bell Labs, now
part of Lucent Technologies) at Murray Hill, NJ, and Holmdel, NJ. This is
where ―Unix‖ was originally developed. It was started as UNICS
(UNiplexedInformation and Computing Service)
Name later changed to UNIX
UC Berkeley is where BSD (Berkeley Systems Distribution) Unix started.
Berkeley UNIX added substantial number of utility programs
Editor –vi
Shell – csh
Ken Thompson and Dennis Ritchie are considered the founders of the Unix
operating system. Ritchie was also instrumental in developi ng and
standardizing the C programming language.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 1
MC7404 NETWORK PROGRAMMING
UNIT – I
Richard Stallman, who was working for MIT, is the founder of the GNU
Project to develop a complete Unix-like, free operating system (GNU is
Not Unix). He started with GNU Emacs and, with many others, develop ed
everything but a kernel.
Linus Torvalds is a programmer who develops a product that mimics the
form and function of a Unix system but is not derived from licensed source
code. Note that ―Linux‖ is not a registered Unix system.
Designed as an interactive OS
Handles multiple processes and multiple users at the same time
Hardware independence
It is Simple, elegant, consistent
UNIX Components
Architecture Diagram of UNIX
Kernel:
The kernel is the heart of the UNIX operating system.
It interacts with hardware
It is responsible for scheduling running of user and other processes.
It is responsible for allocating memory.
It is responsible for managing the swapping between memory and disk.
It is responsible for moving data to and from the peripherals.
It receives service requests from the processes and honours them.
Shell
Whenever you login to a Unix system you are placed in a shell program. The
shell's prompt is usually visible at the cursor's position on your screen. To get
your work done, you enter commands at this prompt.
The shell is a command interpreter; it takes each command and passes
it to the operating system kernel to be acted upon. It then displays the
results of this operation on your screen.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 2
MC7404 NETWORK PROGRAMMING
UNIT – I
Several shells are usually available on any UNI X system, each with its own
strengths and weaknesses.
Different users may use different shells. Initially, your system adminstrator
will supply a default shell, which can be overridden or changed. The most
commonly available shells are:
o Bourne shell (sh)
o C shell (csh)
o Korn shell (ksh)
o TC Shell (tcsh)
o Bourne Again Shell (bash)
Each shell also includes its own programming language. Command files,
called "shell scripts" are used to accomplish a series of tasks.
Utilities
UNIX provides several hundred utility programs, often referred to as
commands.
Example of Commands are cp,mv,sort,rm,rmdir
Divided into six categories
File and directory manipulation commands
Example: cp a b | ls*.*
Filters
Example: grep(extracts lines containing patterns), cut, paste,
Program development tools such as editors/compilers
Example: cc (C compiler), make (maintain large programs whose source code
consists of multiple files)
Text processing
Example: vi
System administration
Example: mount (mount file system)
Miscellaneous
Example: kill 1325 (kill a process), chmod(change privileges of a file)
Modular: single functions can be grouped to perform more complex tasks
Files and Directories: All data in UNIX is organized into files. All files are
organized into directories.
These directories are organized into a tree-like structure called the filesystem
(ii) FILES AND DIRECTORIES File System:
The UNIX file system is a hierarchical arrangement of directories and files.
Everything starts in the directory called root whose name is the single
character.
Directory:
A directory is a file that contains directory entries. Each directory entry contains
a file name along with a structure of information describing the attributes of the
file.
The some of the attributes of a file are,
Type of file – regular file
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 3
MC7404 NETWORK PROGRAMMING
UNIT – I
Directory - the size of the file
The owner of the file
Permissions for the file.
Filename:
The names in a directory are called filenames. The only two characters that
cannot appear in a filename are the slash character (/) and the null character.
Two filenames are automatically created whenever a new directory is created:
(i) . [called dot] – Current Directory
(ii) ..[called dot-dot] – Parent Directory
Pathname:
A sequence of one or more filenames separated by slashes and optionally
starting with a slash, forms a pathname.
A pathname that begins with a slash is called an absolute pathname.
Relative pathnames refer to files relative to the current directory
Working Directory:
Every process has a working directory, also called the current working directory
from which all relative paths are interpreted.
A process can change its working directory with the chdir function.
Home Directory:
When the user logs in, the working directory is set to the user‗s home directory.
This user‗s home directory is obtained from the user‗s entry in the password file.
(iii) INPUT AND OUTPUT
File Descriptors:
File descriptors are normally small non-negative integers that the kernel uses
to identify the files being accessed by a particular process. Whenever the user
opens an existing file or creates a new file, the kernel returns a file descriptor
that the user uses to read the file or write into the file.
All shells open three descriptors namely, (i) Standard input
(ii) Standard output
(iii) Standard error.
The ls‗ command provide away to redirect any or all of these three descriptors to
any file.
Unbuffered I/O:
Unbuffered I/O is provided by the functions open, read, write, lseek and close.
These functions all work with file descriptors.
Standard I/O:
The standard I/O functions provide a buffered interface to the unbuffered I/O
functions. The fgets() reads an entire line whereas the read() reads a specified
number of bytes.
File I/O operations
Most Unix file I/O can be performed with six functions:
open
close
read
write
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 4
MC7404 NETWORK PROGRAMMING
UNIT – I
lseek
dup, dup2
These functions are part of the POSIX standard for UNIX programming, not part
of ANSI C
A process may have several open files which it may be reading from and writing
to. It also has a current position within the file, which is the next byte to be read
or written. Each process has its own array to keep track of
The file opened.
The files status (whether open for reading or writing: the file status flags )
The current offset within the file
When a file is opened or created by a process the kernel assigns a position in
the array called the file descriptor. Each entry of this array actually contains a
pointer to a file table which stores each of the three pieces of information: file,
file status flags, and offset. The file table does not itself contain the file, but
instead has a pointer to another table (called the vnode table), which has vital
information about the file, including its location in memory. The vnode table is
unique for each file.
file descriptor  file table  vnode table
It turns out to be very flexible:
Different processes can have file descriptors for the same file.
A single process can have several file descriptors for the same file
through different file tables.
A single process can have different file descriptors for the same file table.
Different process can have different file descriptors for the same file table.
(The processes must be related as parent to child, or grandchild. This
involves forking.)
PROGRAMS AND PROCESSES:
Program:
A program is an executable file residing on disk in a directory. A program is read
into memory and is executed by the kernel.
Process:
An executing instance of a program. Some operating systems use the
term task to refer to a program that is being executed.
Every process has a unique numeric identifier called the process ID.
The process ID is always a non-negative integer.
Process Control:
The UNIX system provides three primary functions for process control. This
includes,
(i)
the creation of new processes – fork()
(ii)
Program execution – exec()
(iii)
Process termination – waitpid()
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 5
MC7404 NETWORK PROGRAMMING
UNIT – I
(v) USER IDENTIFICATION: User ID
The user ID entry in the password file is a numeric value that identifies the user
to the system. This user ID is assigned by the system administrator when the
login name is assigned, and the user cannot change it. The userID is normally
assigned to be unique for every user.
Eg:
userID 0 is referred as root or the supervisor.
Group ID
The entry in the password file also specifies the numeric group ID which is
assigned by the system administrator when the login name is assigned. The
password file contains multiple entries that specify the same group ID. The
group file that maps group names into numeric group ID‗s is /etc/group.
(vi) SIGNALS:
Signals are a technique used to notify a process that some condition has
occurred.
(vii) TIME VALUES:
UNIX systems have maintained two different time values:
Calendar time.
This value counts the number of seconds since January 1, 1970, Coordinated
Universal Time(UTC). These time values are used to record the time when a file
was last modified. The primitive system data type time-t holds these time
values.
Process time:
It measures the central processor resources used by a process. Process time is
measured in clock ticks. Process time is also called CPU time. When we
measure the execution time of a process, unix system maintains the following
three values for a process. They are,
Clock time.
User CPU time.
System CPU time.
Clock time: The clock time is the amount of time the process takes to run, and
its value depends on the number of other processes being run on the system.
User CPU time: The user CPU time is the CPU time attributed to user
instructions.
System CPU time: The System CPU time is the CPU time attributed to the
kernel when it executes on behalf of the process.
The sum of user CPU time and system CPU time is often called the CPU time.
The time(1) command is used to measure the clock time, user time and system
time of any process.
ENVIRONMENT OF A UNIX PROCESS
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 6
MC7404 NETWORK PROGRAMMING
UNIT – I
The only active entities in a UNIX system are the processes.
UNIX processes are very similar to the classical sequent ial processes or task
Each process runs a single program and initially has a single thread of control
UNIX is a multiprogramming system, so multiple, independent processes may be
running at the same time.
Each user may have several active processes at once, so on a large system,
there may be hundreds or even thousands of processes running.
When a program is being executed on the UNIX system, the system creates a
special environment for that program
Whenever you issue a command in UNIX, it creates, or starts, a new process
A process, in simple terms, is an instance of a running program.
The operating system tracks processes through a five digit ID number known as
the pid or process ID . Each process in the system has a unique pid.
Daemons
On Single -user workstations, even when the user is absent, dozens of
background processes, called daemons, are running. These are started
automatically when the system is booted. (‗‗Daemon‘‘ is a variant spelling of
‗‗demon,‘‘ which is a self-employed evil spirit.)
Example of a Daemon
A typical daemon is the cron daemon. It wakes up once a minute to check if
there is any work for it to do. If so, it does the work. Then it goes back to sleep
until it is time for the next check
Applications of Daemon
Daemon are set to check regular back up updates
Handle incoming and outgoing mail
Processes are created in UNIX in an especially simple manner. The fork system
call creates an exact copy of the original process. The forking process is called
the parent process. The new process is called the child process. The parent
and child each have their own, private memory images. If the parent
subsequently changes any of its variables, the changes are not visible to the
child, and vice versa.
Process Environment
main Function
A C program starts executions with a function main(). The prototype for the main
function without command line arguments is
int main()
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 7
MC7404 NETWORK PROGRAMMING
UNIT – I
#include <stdio.h>
int main()
{
int i,fac1=1,n;
printf(" Enter the value of N : ");
scanf("%d",&n);
for(i=1;i<=n;i++)
fac1 = fac1 * i;
printf("factorial is %d",fac1);
}
//output
sh-4.2# vi fact1.c
sh-4.2# cc fact1.c
sh-4.2# ./a.out
Enter the value of N : 4
factorial is 24sh-4.2#
a.out remains the default output file name for executables created by
certain compilers and linkers. ―a‖ refers to assembler output
The prototype of the main function with command line arguments
#include <stdio.h>
main(int argc, char *argv[])
{
int i,fac1=1;
int n = atoi(argv[2]);
for(i=1;i<=n;i++)
fac1 = fac1 * i;
printf("factorial is %d",fac1);
}
sh-4.2# cc fact.c
sh-4.2# ./a.out fact 5
factorial is 120sh-4.2#
where argc is the number of command-line arguments and argv is an array of
pointers to the arguments.
When a C program is executed by the kernel — by one of the exec functions —
a special start-up routine is called before the main function is called. The
executable program file specifies this routine as the starting address for the
program; this is set up by the link editor when it is invoked by the C compiler.
This start-up routine takes values from the kernel — the command line
arguments and the environment — and sets things up so that the main function
is called.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 8
MC7404 NETWORK PROGRAMMING
UNIT – I
C Program Life Cycle: Invocation through Termination
1. When a C program is executed by the kernel by one of the exec
function
2. A start up routine is called before the main() function
3. The startup routine takes arguments from the command li ne
arguments
Process termination:
To terminate a process.
There are eight ways for a process to terminate. These eight ways are divided
under two categories. They are
(a) Normal termination.
(b) Abnormal termination.
Normal termination occurs in five ways. They are,
1. Return from main
2. Calling exit
3. Calling_exit or _Exit
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 9
MC7404 NETWORK PROGRAMMING
UNIT – I
4. Return of the last thread from its start routine
5. Calling pthread_exit from the last thread
Abnormal termination occurs in three ways. They are,
6. Calling abort
7. Receipt of signal
8. Response of the last thread to a cancellation request
Return from main:
If the start-up routine were coded in ‗C‗ the call to main could look like,
exit(main(argc, argv));
Returning an integer value from the main function is equivalent to calling exit
with same value. Thus,
exit(0); is the same as
return(0); from the main function.
Exit Functions:
The following three functions
(a) _exit
(b) _Exit and
(c) exit terminate a program normally.
The _exit() and _Exit(), returns to the kernel immediately but exit(),
performs certain cleanup processing and then returns to the kernel.
The prototype is as follows,
#include<stdlib.h>
void exit(int status);
void _Exit(int status);
#include<unistd.h>
void _exit(int status);
The Death of a Process
exit() and _exit() and _Exit()
There are three ways to forcefully exit a program:
1. _exit() : System calls that request the O.S. to terminate a process
immediately without any additional code execution.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 10
MC7404 NETWORK PROGRAMMING
UNIT – I
2. exit() : C Standard Library exit procedure that will cleanly terminate a
process by invoking additional code as requested by the user and to
manage ongoing I/O.
3. _Exit() : C Standard Library exit procedure that will immediately terminate
a process, essentially a wrapper to _exit()
I/O Buffering and Exit Procedures
One aspect of the standard library exit procedure is to handle I/O buffering that
occurs within the C standard library.
Figure 3: C Program Life Cycle: Standard I/O Cleanup
Buffering is one way to avoid excessive calls. When you call printf() or another
standard I/O library function that is printing to the terminal or a file, the print
does not occur right away. Instead, it is buffered, or temporarily stored and
waiting to be completed. A print will become unbuffered whenever the buffer is
full, e.g., there is enough bytes to write and cannot store any more, or when a
line completes, as defined by printing a newline symbol.
Case 1
Return from main()
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
printf("Hello");
exit(0);
}
exit() function is used to terminate a process
exit() flushes (cleans the) the IO related buffer before exiting the process and
calls the _exit() function.
Sample code with exit function:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 11
MC7404 NETWORK PROGRAMMING
UNIT – I
int main()
{
printf("Hello");
exit(0);
}
Output:
admin@nirmala ~
$ cc exit.c
admin@nirmala ~
$ ./a
Hello
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
printf("Hello");
_exit(0);
}
outPut:
admin@nirmala ~
$ cc exit.c
admin@nirmala ~
$ ./a
admin@nirmala ~
It prints nothing.
Explanation:
This is due to ,we called _exit() function directly, so IO related data is not
flushed, so printf data is not flushed, because of this, it has printed nothing.
Sample code with _exit function with \n:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
printf("Hello\n");
_exit(0); //or _Exit(0); // they are equivalent
}
OutPut:
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 12
MC7404 NETWORK PROGRAMMING
UNIT – I
sh-4.2# cc exit.c
sh-4.2# ./a.out
Hello
We got the output Hello, this is due to we are forcefully flushing the data using
'\n'. Infact printf() function wont print or flush the data until buffer completes or
end of the character is \n. printf internally maintains some buffer.
Abnormal termination occurs in three ways:
6. Calling abort
7. Receipt of a signal
8. Response of the last thread to a cancellation request
atexit() Exit Handlers
atexit - register a function to be called at normal process termination
atexit function:
A process can register up to 32 functions that are automatically called by exit.
These
are called exit handlers and are registered by calling the atexit function.
Syntax:
#include <stdlib.h>
int atexit (void (*func)(void));
Here, the user pass the address of a function as the argument to atexit .When
this function is called it, is not passed any arguments and is not expected to
return a value.
Syntax
The atexit() function registers the given function to be called at normal process
termination, either via exit(3) or via return from the program's main(). Functions
so registered are called in the reverse order of their registration; no
arguments are passed.
The same function may be registered multiple times: it is called once for each
registration.
The atexit() function returns the value 0 if successful; otherwise it returns a
nonzero value
#include
<stdio.h>
#include
<stdlib.h>
void my_exit1(void);
void my_exit2(void);
int main(void)
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 13
MC7404 NETWORK PROGRAMMING
UNIT – I
{
int k;
if (atexit(my_exit1) != 0)
{
printf("cant register my_exit1 ");
exit(0);
}
k = atexit(my_exit2);
if (k != 0)
{
printf("can't register my_exit1");
exit(0);
}
return(0);
}
void my_exit1(void)
{
printf("first exit handler\n");
}
void my_exit2(void)
{
printf("second exit handler\n");
}
Exit Statuses
The last bit of the exit() puzzle is exit status. Every program exits with some
status.
_exit(int status);
exit(int status);
_Exit(int status);
Additionally, the return value of main() implicitly sets the exit status. Convention
indicates the following exit status:
0 : success
1 : failure
2 : error
Memory Layout of a C program
Historically a C program has been composed of
o Text segment
o Initialised data segment
o Uninitialised data segment
o Stack
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 14
MC7404 NETWORK PROGRAMMING
UNIT – I
o Heap
Text segment
o machine instructions, executed by the CPU
o sharable, only a single copy needs to be in the memory for frequently
executed program
o read-only, to prevent a program from being accidently modifying its
instructions
Initialised data segment (or data segment)
o contains variables that are specifically initialised in the program
e.g.
o
int max =
;
Unintialised data segment
o often called ―bss‖ segment -- block started by symbol
o data is initialised by the kernel to be before the program starts executing
o e.g.
o
long sum[
; appear outside any function ==> stored in uninitialised
data segment
Stack
o stores automatic variables + information saved each time a function is called
Heap
o Dynamic memory allocation usually takes place on the heap
o Normally located between the uniintialised data segment and the stack
PROCESS CONTROL
The process control provided by the UNIX system includes,
The creation of new processes
Program execution
Program termination
Process Identifiers:
Every process has a unique process ID which is a non-negative integer. There
are some special processes available.
Example:
(i) Process ID 0 is usually the scheduler process and is often known as the
swapper. It is a part of the kernel and is called the system process
(ii) Process ID 1 is usually the init process and is invoked by the kernel at the
end of the bootstrap procedure. It is a normal process and not a system
process.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 15
MC7404 NETWORK PROGRAMMING
UNIT – I
(iii) Process Id 2 is the page daemon responsible for su pporting the paging of
the virtual memory system.
In addition to the process ID, there are other identifiers for every process. The
following function returns these identifiers
#include<unistd.h>
pid_t getpid(void) Returns: process Id of calling process
pid_t getppid(void)  Returns: parent process ID of calling process
uid_t getuid(void)  Returns : real user ID of calling process
uid_t geteuid(void)  Returns: effective user ID of calling process
gid_t getgid(void)  Returns: real group ID of calling process
gid_t getegid(void) Returns: effective group ID of calling process
Process Creation in UNIX
Every process, except process 0, is created by the fork() system call
fork() allocates entry in process table and assigns a unique PID to the child
process
child gets a copy of process I
mage of parent: both child and parent are executing the same code following
fork() but fork() returns the PID of the child to the parent process and returns 0
to the child process
Process 0 is created at boot time and becomes the ―swapper‖ after forking
process 1 (the INIT process)
When a user logs in: process 1 creates a process for that user
Process creation
There are three distinct phases in the creation of a process
1. Forking
2. Overlaying and execution
3. Waiting
Forking
Forking is the first phase in the creation of a process by a process.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 16
MC7404 NETWORK PROGRAMMING
UNIT – I
The calling process (parent) makes a call to the system routine fork() which then
makes an exact copy of itself.
Right after the fork() there will be 2 processes with identical memory images.
Each one of these 2 processes has to return from the fork() system call.
Thus there will be 2 return values.
The fork of the parent process returns the PID of the new processes, that is the
child process just created, whereas the fork of the child returns a 0. If a new
child is process is not created a -1 is returned
Child gets a copy of parents text, data , heap and stack
Instead of completely copying we can use COW copy on write technique is used.
These regions are shared by the parent and the child and have their protection
changed by the kernel to read only.
Immediately after forking the parent makes a system call to one of the wait()
functions. The paren‘t waits for the child process to complete its task
There are also symbolic constants defined in unistd.h for the file descriptors
belonging to the standard streams stdin, stdout, and stderr; see Standard
Streams.
STDIN_FILENO
This macro has value 0, which is the file descriptor for standard input.
STDOUT_FILENO
This macro has value 1, which is the file descriptor for standard output.
STDERR_FILENO
This macro has value 2, which is the file descriptor for standard error
output.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 17
MC7404 NETWORK PROGRAMMING
UNIT – I
#include
#include
#include
#include
<sys/types.h>
<stdio.h>
<sys/wait.h>
<unistd.h>
int glob = 6;
/* external variable in initialized data */
char
buf[ ] = "a write to stdout\n";
int main(void)
{
Int var;
/* automatic variable on the stack */
pid_t pid;
var = 88;
if (write(STDOUT_FILENO,buf, sizeof(buf)-1) != sizeof(buf)-1)
printf("write error");
printf("before fork\n");
if ( (pid = fork()) < 0)
printf("fork error");
else if (pid == 0)
{
/* child */
glob++;
/* modify variables */
var++;
}
else
sleep(2);
/* parent */
printf("pid = %d, glob = %d, var = %d ppid = %d\n", getpid(), glob, var,
getppid());
exit(0);
}
admin@nirmala ~
$ ./a
a write to stdout
before fork
pid = 4168, glob = 7, var = 89
pid = 4140, glob = 6, var = 88
Signals
A signal is an asynchronous event which is delivered to a process. Signals are
called as software interrupts
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 18
MC7404 NETWORK PROGRAMMING
UNIT – I
Asynchronous means that the event can occur at any time
– may be unrelated to the execution of the process
– e.g. user types ctrl-C, or the modem hangs
An important feature of signals is that they are asynchronous, which means that
a process may receive a signal at any time during its execution, and must be
prepared to respond to the signal at that time
Signals are usually sent by the Operating System (kernel) to notify processes
that some event has occurred. By their nature, signals interrupt whatever the
process is doing at that moment, and force it to handle them immediately
Signal Sources:
Hardware - division by zero
Kernel – notifying an I/O device for which a process has bee n waiting is
available
Other Processes – a child notifies its parent that it has terminated
User – key press (i.e., Ctrl-C)
Syntax
signal() is a function that accepts two arguments and returns a pointer to a
function that takes one argument, the signal handler, and returns nothing.
If the call fails, it returns SIG_ERR.
The arguments are
The first is an integer (i.e., int), a signal name.
The second is a function that accepts an int argument and returns nothing, the
signal handler.
If you want to ignore a signal, use SIG_IGN as the second argument.
If you want to use the default way to handle a signal, use SIG_DFL as the
second argument
Examples
The following ignores signal SIGINT
signal(SIGINT, SIG_IGN);
The following uses the default way to handle
SIGALRM
signal(SIGALRM, SIG_DFL);
The following installs function INThandler()
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 19
MC7404 NETWORK PROGRAMMING
UNIT – I
as the signal handler for signal SIGINT
signal(SIGINT, INThandler);
Procedure
Prepare a function that accepts an integer, a signal name, to be a signal
handler.
2. Call signal() with a signal name as the first argument and the signal handler
as the second.
3. When the signal you want to handle occurs your signal handler is called with
the argument the signal name that just occurred.
4. Two important notes:
a. You might want to ignore that signal in your handler
b. Before returning from your signal handler, don‘t forget to re -install it.
For example, the user may want to stop the process any time by pressing
Control-C, which results in SIGINT signal.
Each signal has an integer number, as well as a symbolic name associated with
it. There are 30 odd signals and all these names begin with the three characters
SIG
Linux supports 31 different signals
They are accessed by the header file <signal.h>
value symbol
purpose
1
SIGHUP
hangup on control terminal
2
SIGINT
interrupt from keyboard (Ctrl-c)
3
SIGQUIT quit from keyboard (Ctrl-\)
8
SIGFPE
floating point exception (e.g. divide by 0)
9
SIGKILL
terminate receiving process
14
SIGALRM end of alarm() system call timeout
15
SIGTERM default kill command signal
17
SIGCHLD child process stopped or terminated
19
SIGSTOP stop execution from keyboard Ctrl-z
There are about 25 different kinds of signals, depending on the flavor of the
system. Use the command kill -l, to get the list of signals supported by your
system
admin@nirmala ~
$ kill -l
1) SIGHUP
2) SIGINT
3) SIGQUIT
4) SIGILL
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 20
MC7404 NETWORK PROGRAMMING
UNIT – I
5) SIGTRAP
6) SIGABRT
7) SIGEMT
8) SIGFPE
9) SIGKILL
10) SIGBUS
11) SIGSEGV
12) SIGSYS
13) SIGPIPE
14) SIGALRM
15) SIGTERM
16) SIGURG
17) SIGSTOP
18) SIGTSTP
19) SIGCONT
20) SIGCHLD
21) SIGTTIN
22) SIGTTOU
23) SIGIO
24) SIGXCPU
25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF
28) SIGWINCH
29) SIGLOST
30) SIGUSR1
31) SIGUSR2
For some signals, the default behavior is to ignore the signal. For others, the
default behavior is to terminate the process.
The process can catch most of the signals except for a few. The process cannot
catch SIGKILL & SIGSTOP signals. W hen the process receives such signals, it
will be terminated.
What is signal handling?
We all have faced the traffic signals. How do we handle it? Green? we go
ahead. Yellow? we slow down. Red? we stop.
Same way how a program (process) handles the signals it receives is referred to
as signal handling.
How to handle signals?
How did we learn to handle signals? Somebody, probably our parents taught us.
The user tells the program what to do when it receives a signal. Similarly, you
need to tell your program what should it do when it receives a signal and that is
called as signal handling
Programming Signal Handling
THE SIGNAL
The signal what is to be handled whould be known.
THE HANDLER
The handler is the main thing used to handle signals
It gets the signal and performs whatever we want it to do with the signal.
THE CONNECTION
How to connect the signal with the handler? The program should know which
handler is associated with which signal
We can have different handlers for different signals. The proce ss of setting up
the handler for a signal is called as signal set up.
signal function
The signal function connects the signal with the handler. Below example shows
a very basic signal handling.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 21
MC7404 NETWORK PROGRAMMING
UNIT – I
#include<stdio.h>
#include<signal.h>
void sigHandlerFunc(int sig); //signal handler prototype
int main()
{
int i;
for(i=0;i<5;i++)
{
printf(" \n Number %d",i);
signal(SIGUSR1, sigHandlerFunc); //signal is declared and called
raise(SIGUSR1);
}
return 0;
}
void sigHandlerFunc(int sig)
{
printf("\n Hey there! Just got this signal %d",sig);
}
//output
Number 0
Hey there!
Number 1
Hey there!
Number 2
Hey there!
Number 3
Hey there!
Number 4
Hey there!
Just got this signal 30
Just got this signal 30
Just got this signal 30
Just got this signal 30
Just got this signal 30
The process cannot catch SIGKILL & SIGSTOP signals. When the process
receives such signals, it will be terminated
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
/*
* signal handler
*/
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 22
MC7404 NETWORK PROGRAMMING
UNIT – I
void CatchInterrupt (int signum)
{
pid_t my_pid;
printf("\nReceived an interrupt! About to exit ..\n");
fflush(stdout);
my_pid = getpid();
kill(my_pid, SIGKILL);
}
int main(int argc, char** argv) {
/*
* Set the INT (Ctrl-C) signal handler to 'CatchInterrupt'
*/
signal(SIGINT, CatchInterrupt);
/*
* Do Nothing and wait for interrupts
*/
for ( ;; ) {}
}
In the above program, the process simply waits in an infinite loop, for an
interrupt event to occur and as soon as it receive one, it exits after printing a
message on the console.
//output
//create a signal by pressing ctrl + c
$ ./a
Received an interrupt! About to exit ..
Killed
Sleep
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
Returns: 0 or number of unslept seconds.
This function causes the calling process to be suspended until either
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 23
MC7404 NETWORK PROGRAMMING
UNIT – I
•
The amount of wall clock time specified by seconds has elapsed. The
return value is 0.
A signal is caught by the process and the signal handler returns. Return value is
the number of unslept seconds.
#include <stdio.h>
#include <signal.h>
/*
* number of times the handle will run:
*/
int count = 3;
void handle(int sig) {
printf("\n network programming \n");
--count;
alarm(1);
}
int main() {
signal(SIGALRM, handle);
alarm(1);
while(count)
{
sleep(1);
}
printf("done\n");
return 0;
}
admin@nirmala ~
$ cc sig7.c
admin@nirmala ~
$ ./a
network programming
network programming
network programming
done
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 24
MC7404 NETWORK PROGRAMMING
UNIT – I
INTERPROCESS COMMUNICATION
InterprocessCommunication (IPC) enables processes to communicate with each
other to share information
Interprocess communication has 2 forms
IPC is used for 2 functions:
1) Synchronization---Used to coordinate access to resources among processes
and also to coordinate the execution of these processes. They are
Record locking,
Semaphores,
Mutexes and Condition variables.
2) Message Passing---Used when processes wish to exchange information.
Message passing takes several forms such as :
Pipes,
FIFOs,
Message Queues,
Shared Memory.
File or Record Locking:
Used to ensure that a process has exclusive access to a file before using it.
Simple Client-Server or IPC model:
Pipes
A pipe provides a one way flow of data
#include <unistd.h>
int pipe(int fildes[2]);
fildes[0] is open for reading and fildes[1] is open for
writing
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 25
MC7404 NETWORK PROGRAMMING
UNIT – I
The output of fildes[1] is the input for fildes[0]
//pipe creation and its usage
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
main()
{ int pipefd[2], n;
char buff[100];
if (pipe(pipefd) < 0 ) printf("pipe error"); //pipe not created
printf("read fd = %d, write fd = %d \n", pipefd[0], pipefd[1]);
printf("\n The word written in pipe ");
write(pipefd[1], "HELLO WORLD" , 12);
n = read(pipefd[0],buff,sizeof(buff));
write(1, buff, n); /*fd=1=stdout*/
}
//output
admin@nirmala ~
$ ./a
read fd = 3, write fd = 4
HELLO WORLD The word written in pipe is
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
void client(int readfd, int writefd)
{
char msg[100];
int n;
char eof = EOF;
printf("\n Enter msg to be sent to server: " );
fgets(msg, 100, stdin);
if (write(writefd, msg, strlen(msg) - 1) == -1){
perror("error writing...");
exit(0);
}
if ((n = read(readfd, msg, 100)) < 0) {
perror("error reading...");
exit(0);
}
msg[n] = '\0';
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 26
MC7404 NETWORK PROGRAMMING
UNIT – I
printf(" \n received from server: %s", msg);
}
void server(int readfd, int writefd)
{
char msg[100];
int n;
if ((n = read(readfd, msg, 100)) < 0) {
perror("error reading...");
}
msg[n] = '\0' ;
printf("\n server received from client: %s ",msg);
printf("\n enter msg to be sent to client: ");
fgets(msg, 100, stdin);
write(writefd, msg, strlen(msg) - 1);
}
int main()
{
int pipe1fd[2], pipe2fd[2];
int pid;
/* create two pipes */
if (pipe(pipe1fd) == -1) {
perror("pipe:");
return 0;
}
if (pipe(pipe2fd) == -1) {
perror("pipe:");
return 0;
}
/* start child process and run client code in it */
pid = fork();
if (pid == 0) {
close(pipe1fd[1]);
//close the write end of the first pipe
close(pipe2fd[0]);
//close the read end of the second pipe
client(pipe1fd[0], pipe2fd[1]);
exit(0);
}
else {
/* code that runs in parent ; runs as server */
close(pipe1fd[0]); // close read end of the first pipe
close(pipe2fd[1]); // close write end of the second pipe
server(pipe2fd[0], pipe1fd[1]);
wait(NULL);
//wait for child process to finish
return 0;
}
}
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 27
MC7404 NETWORK PROGRAMMING
UNIT – I
OUTPUT
admin@nirmala ~
$ ./a
Enter msg to be sent to server: hello
server received from client: hello
enter msg to be sent to client: hai
received from server: hai
The program above creates two pipes and use them for two way communication
between client and server
1. Create two pipes, pipe1 (pipe1fd[2]) and pipe2 (pipe2fd[2]).
2. call fork to create a child process and let child process run client code
3. In child process close write end of pipe1 (pipe1fd[1]) and read end
of pipe2 (pipe2fd[0])
4. parent process close read end of pipe1 (pipe1fd[0]) and write end of
pipe2 (pipe2fd[1])
If all file descriptors referring to the write end of a pipe have been
closed, then an attempt to read from the pipe will see en d-of-file (read
will return 0).If all file descriptors referring to the read end of a
pipe have been closed, then a write will cause a SIGPIPE signal to be
generated for the calling process.
Properties of Pipe:
1) Pipes do not have a name. For this reason, the processes must share a
parent process. This is the main drawback to pipes.
2) Pipes do not distinguish between messages; they just read a fixed number of
bytes. Newline (\n) can be used to separate messages. A structure with a length
field can be used for message containing binary data.
3) Pipes can also be used to get the output of a command or to provide input to
a command
FIFOs–named pipes
With regular pipes, only processes with a common ancestor can communicate
With FIFOs, any two processes can communicate
Creating and opening a FIFO is just like creating and opening a file
Definition:
A FIFO is similar to a pipe. A FIFO (First In First Out) is a one -way flow of data.
FIFOs have a name, so unrelated processes can share the FIFO. FIFO is a
named pipe. This is the main difference between pipes and FIFOs.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 28
MC7404 NETWORK PROGRAMMING
UNIT – I
Creat: A FIFO is created by the mkfifo function:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
pathname – a UNIX pathname (path and filename). The name of the FIFO
mode – the file permission bits.
FIFO can also be created by the mknod system call,
e.g., mknod(―fifo1‖, S_IFIFO|0666, 0) is same as mkfifo(―fifo1‖, 0666).
Open: mkfifo tries to create a new FIFO. If the FIFO already exists, then an
EEXIST error is returned. To open an existing FIFO, use open(), fopen() or
freopen()
Close: to close an open FIFO, use close(). To delete a created FIFO, use
unlink().
Properties: ( Some of them are also applicable to PIPES)
1) After a FIFO is created, it can be opened for read or write.
2) Normally, opening a FIFO for read or write, it blocks until another process
opens it for write or read.
mode : The file protection mode usually given by 9 bits indicat ing rwx
permission
The flag codes are given by
O_RDONLY
-- opens file for read only
O_WRONLY – opens file for write only
O_RDWR – opens file for reading and writing
O_NDELAY
– prevents possible blocking
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 29
MC7404 NETWORK PROGRAMMING
UNIT – I
O_APPEND
--- opens the file for appending
O_CREAT -- creates the file if it does not exists
O_TRUNC -- truncates the size to zero
O_EXCL
– produces an error if the O_CREAT bit is on and file exists
Open: mkfifo tries to create a new FIFO. If the FIFO already exists, then an
EEXIST error is returned. To open an existing FIFO, use open(), fopen() or
freopen()
Close: to close an open FIFO, use close(). To delete a created FIFO, use
unlink().
Properties: (mode – the file permission bits)
There are file access permissions and there are nine permission bits for each
file divided into 3 categories.
st_mode
mask
S_IRUSR
S_IWUSR
S_IXUSR
S_IRGRP
S_IWGRP
S_IXGRP
S_IROTH
S_IWOTH
S_IXOTH
Meaning
Examples
user-read
user-write
user-execute
group-read
group-write
groupexecute
other-read
other-write
otherexecute
chmod
chmod
chmod
chmod
chmod
chmod
u+r
u+w
u+x
g+x
g+x
g+x
Set - chmod u+rwx
Unset – chmod u-rwx
chmod o+x
chmod o+x
chmod o+x
Set - chmod o+rwx
Unset – chmod o-rwx
Set - chmod g+rwx
Unset – chmod g-rwx
Chmod - used to change the file permissions to a existing file
To check whether the permissions has been set
ls –l filename
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 30
MC7404 NETWORK PROGRAMMING
UNIT – I
admin@nirmala ~
$ ls -l a.c
----rwxrwx 1 admin
mkpasswd
52 Jan 21 22:22 a.c
For IPC FIFO
Sender process
Receiver process
A Channel to pass the data
In our case it is FIFO
Algorithm (Client Side)
1. Start.
2. Open well known server FIFO in write mode.
3. Write the pathname of the file in this FIFO and send the request.
4. Open the client specified FIFO in read mode and wait for reply.
5. When the contents of the file are available in FIFO, display it on the
terminal
6. Stop.
Algorithm (Server Side)
1. Start.
2. Create a well known FIFO using mkfifo()
3. Open FIFO in read only mode to accept request from clients.
4. When client opens the other end of FIFO in write only mode, then read the
contents and store it in buffer.
5. Create another FIFO in write mode to send replies.
6. Open the requested file by the client and write the contents into the client
specified FIFO and terminate the connection.
7. Stop.
//fifo writer
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd;
char *msg;
char * myfifo = "myfifo";
/* create the FIFO (named pipe) */
mkfifo(myfifo, 0666);
/* write a message to the FIFO */
fd = open(myfifo, O_WRONLY);
printf(―\n Enter the message to send : ‖);
scanf(―%s‖,msg);
write(fd, msg, sizeof(msg));
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 31
MC7404 NETWORK PROGRAMMING
UNIT – I
close(fd);
/* remove the FIFO */
unlink(myfifo);
return 0;
}
//fifo reader
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#define MAXBUF 1024
int main()
{
int fd;
char * myfifo = "myfifo";
char buf[MAXBUF];
/* open, read, and display the message from the Fifo */
fd = open(myfifo, O_RDONLY);
read(fd, buf, MAXBUF);
printf("Received: %s \n", buf);
close(fd);
return 0;
}
//execute writer first
[root@localhost ~]# cc fifowriter.c
[root@localhost ~]# ./a.out
Enter the message to send : hello
[root@localhost ~]#
//output reader
[root@localhost ~]# cc fiforeader.c
[root@localhost ~]# ./a.out
Received: hello
[root@localhost ~]#
Message Queues
Drawback of PIPE and FIFO:
1) Pipe or FIFO is an unformatted stream. Message queue is a formatted stream
consisted of messages.
2) Pipe or FIFO has to be read in the same order as they are written. Message
queue can be accessed randomly.
3) Pipe or FIFO is unidirectional. Message queue is bidirectional.
4) Pipe or FIFO is simplex. Message queue is multiplex.
5) Message queue is faster since it is in kernel.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 32
MC7404 NETWORK PROGRAMMING
UNIT – I
Message Queue Properties
Unlike pipes and FIFOs, message queues support messages that have
structure.
Message queues are are persistent objects that must be initially created and
eventually deleted when no longer required.
Message queues are created with a specified maximum message size and
maximum number of messages.
Message queues are created and opened using a special version of the open
system call, mq_open.
It is identified by an queue identifier
Linked list of messages stored in the kernel
Identifier by a message queue identifier
Created or opened with msgget()
Messages are added to the queue with msgsnd()
Specifies type, length, and data of msg
Messages are read with msgrcv()
Message format:
A message queue is created or opened using:
int msgget(key_t key, int msgflag)
msgflag — sets permission + IPC_CREAT / IPC_EXCL
msgid — returned by the msgget() function, -1 on error.
Messages are sent using:
int msgsnd(int msgid, struct msgbuf *ptr, int length, int flag)
struct msgbuf -- message format, has a long int (message type) as a field,
immediately followed by the data. Must be filled by caller before calling
msgsnd().
length — determine how many bytes of data portion are sent.
flag — can be IPC_NOWAIT which causes the function to return immediately
with error=EAGAIN if no queue space is available. Default action is to block.
return — 0 if successful; -1 on error.
Messages are received using:
int msgrcv(int msgid, struct msgbuf *ptr, int length, long msgtype, int flag)
length — specify the size of the data buffer. Error if the message is too long.
OK if the length ≥ message length which is determined by msgsnd(… length…).
flag — if set to MSG_NOERROR, long messages are truncated and the rest is
discarded.
//IPC message send
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 33
MC7404 NETWORK PROGRAMMING
UNIT – I
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSIZE
128
void die(char *s)
{
perror(s);
exit(1);
}
struct msgbuf
{
long mtype;
char mtext[MAXSIZE];
};
main()
{
int msqid;
int msgflg = IPC_CREAT | 0666;
key_t key;
struct msgbuf sbuf;
size_t buflen;
key = 1234;
if ((msqid = msgget(key, msgflg )) < 0) //Get the message queue ID for the
given key
die("msgget");
//Message Type
sbuf.mtype = 1;
printf("Enter a message to add to message queue : ");
scanf("%[^\n]",sbuf.mtext);
getchar();
buflen = strlen(sbuf.mtext) + 1 ;
if (msgsnd(msqid, &sbuf, buflen, IPC_NOWAIT) < 0)
{
printf ("%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buflen);
die("msgsnd");
}
else
printf("Message Sent\n");
exit(0);
}
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 34
MC7404 NETWORK PROGRAMMING
UNIT – I
//IPC_msgq_rcv.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE
128
void die(char *s)
{
perror(s);
exit(1);
}
typedef struct msgbuf
{
long mtype;
char mtext[MAXSIZE];
};
int main()
{
int msqid;
key_t key;
struct msgbuf rcvbuffer;
key = 1234;
if ((msqid = msgget(key, 0666)) < 0)
die("msgget()");
//Receive an answer of message type 1.
if (msgrcv(msqid, &rcvbuffer, MAXSIZE, 1, 0) < 0)
die("msgrcv");
printf("%s\n", rcvbuffer.mtext);
exit(0);
}
//sender should be executed then receiver program
[root@localhost ~]# cc IPCmsgsend.c
[root@localhost ~]# ./a.out
Enter a message to add to message queue : network
Message Sent
[root@localhost ~]# ./a.out
Enter a message to add to message queue : programming
Message Sent
[root@localhost ~]# ipcs -q
------ Message Queues -------key
msqid
owner
perms
0x000004d2 0
root
666
used-bytes messages
20
2
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 35
MC7404 NETWORK PROGRAMMING
UNIT – I
[root@localhost ~]#
[root@localhost ~]#
Enter a message to
Message Sent
[root@localhost ~]#
cc IPCmsgsend.c
./a.out
add to message queue : laboratory
ipcs -q
------ Message Queues -------key
msqid
owner
perms
0x000004d2 0
root
666
[root@localhost
[root@localhost
network
[root@localhost
programming
[root@localhost
used-bytes messages
31
3
~]# cc IPCmsgrcv.c
~]# ./a.out
~]# ./a.out
~]# ipcs -q
------ Message Queues -------key
msqid
owner
perms
0x000004d2 0
root
666
used-bytes messages
11
1
[root@localhost ~]# ./a.out
laboratory
[root@localhost ~]# ./a.out
[6]+ Stopped
./a.out
[root@localhost ~]# ipcs -q
------ Message Queues -------key
msqid
owner
perms
0x000004d2 0
root
666
used-bytes messages
0
0
[root@localhost ~]# ./a.out
SHARED MEMORY
Sharing memory in POSIX (and many other systems) requires
creating a persistent ―object‖ associated with the shared memory, and allowing
processes to connect to the object.Creating or connecting to the persistent
object is done in a manner similar to that for a file, but uses the shm_open
system call.
In the fork() system call, the parent and children have separateaddress space or
memory. The parent and child will no way communicate and can execute
independent of each other
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 36
MC7404 NETWORK PROGRAMMING
UNIT – I
A shared memory is an extra piece of memory that is attached to some address
spaces for their owners to use. All of these processes share the same memory
segment and have access to it.
Consequently, race conditions may occur if memory accesses are not handled
properly.
The following figure shows two processes and their address spaces. The yellow
rectangle is a shared memory attached to both address spaces and both
process 1 and process 2 can have access to this shared memory as if the
shared memory is part of its own address space.
One process must explicitly ask for an area, using a key, to be shared by other
processes. This process will be called the server. All other processes, the
clients, that know the shared area can access it. However, there is no protection
to a shared memory and any process that knows it can access it freely. To
protect a shared memory from being accessed at the same time by several
processes, a synchronization protocol must be setup.
A shared memory segment is identified by a unique integer, the shared memory
ID.
The shared memory itself is described by a structure of type shmid_ds in
header file sys/shm.h.
To use this file, files sys/types.h and sys/ipc.h must be included.
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
A general scheme of using shared memory is the following:
For a server, it should be started before any client. The server should
perform the following tasks:
1. Ask for a shared memory with a memory key and memorize the
returned shared memory ID. This is performed by system call
shmget().
2. Attach this shared memory to the server's address space with
system call shmat().
3. Initialize the shared memory, if necessary.
4. Do something and wait for all clients' completion
5. Detach the shared memory with system call shmdt().
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 37
MC7404 NETWORK PROGRAMMING
UNIT – I
6. Remove the shared memory with system call shmctl().
For the client part, the procedure is almost the same:
1. Ask for a shared memory with the same memory key and memorize
the returned shared memory ID.
2. Attach this shared memory to the client's address space.
3. Use the memory.
4. Detach all shared memory segments, if necessary.
5. Exit.
shmget()
shm_id = shmget ( key_t k,
/* the key for the segment */
int size, /* the size of the segment */
int flag ); /* create/use flag */
In the above definition, k is of type key_t or IPC_PRIVATE. It is the numeric key
to be assigned to the returned shared memory segment. size is the size of the
requested shared memory. The purpose of flag is to specify the way that the
shared memory will be used. For our purpose, only the following two values
are important:
1. IPC_CREAT | 0666 for a server (i.e., creating and granting read and write
access to the server)
2. 0666 for any client (i.e., granting read and write access to the client)
If shmget( ) can successfully get the requested shared memory, its function
value is a non-negative integer, the shared memory ID; otherwise, the function
value is negative
UNIX requires a key of type key_t defined in file sys/types.h for requesting
resources such as shared memory segments, message queues and
semaphores. A key is simply an integer of type key_t; however, you should not
use int or long, since the length of a key is system dependent
The ftok( ) function has the following prototype:
key_t ftok ( const char *path, /* a path string */
int id /* an integer value */ );
Function ftok( ) takes a character string that identifies a path and an integer
(usually a character) value, and generates an integer of type key_t based on the
first argument with the value of id in the most significant position
Function ftok( ) takes a character string that identifies a path and an integer
(usually a character) value, and generates an integer of type key_t based on the
first argument with the value of id in the most significant position. For example,
if the generated integer is 35028A5D16 and the value of id is 'a' (ASCII value =
6116), then ftok( ) returns 61028A5D16. That is, 6116 replaces the first byte of
35028A5D16,generating 61028A5D16
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 38
MC7404 NETWORK PROGRAMMING
UNIT – I
After a shared memory ID is returned, the next step is to attach it to the address
space of a process. This is done with system call shmat( ). The use of shmat( )
is as follows:
shm_ptr = shmat ( int shm_id, /* shared memory
ID */ char *ptr, /* a character pointer */ int flag
); /* access flag */
System call shmat( ) accepts a shared memory ID, shm_id, and attaches the
indicated shared memory to the program's address space. The returned value is
a pointer of type (void *) to the attached shared memory. Thus, casting is
usually necessary. If this call is unsuccessful, the return value is -1. Normally,
the second parameter is NULL. If the flag is SHM_RDONLY, this shared memory
is attached as a read-only memory; otherwise, it is readable and writable.
Detaching and Removing a Shared Memory Segment - shmdt( ) and shmctl(
):
System call shmdt( ) is used to detach a shared memory. After a shared memory
is detached, it cannot be used. However, it is still there and can be re -attached
back to a process's address space, perhaps at a different address. To remove a
shared memory, use shmctl( ).
Two different processes communicating via shared memory we develop two
programs here that illustrate the passing of a simple piece of memory (a string)
between the processes if running simultaneously:
/* shm_server.c */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#define SHMSIZE 27
main()
{
char c;
int shmid;
key_t key;
char *shm, *s;
/* * We'll name our shared memory segment * "5678". */
key = 5678;
/* * create the segment.* */
if ((shmid = shmget(key, SHMSIZE, IPC_CREAT | 0666)) < 0)
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 39
MC7404 NETWORK PROGRAMMING
UNIT – I
{
perror("shmget");
exit(1);
}
printf("%d",shmid);
/** Now we attach the segment to our data space.*/
shm = (char*) shmat(shmid, NULL,0);
if (shm == (char *)-1)
{
perror("shmat");
exit(1);
}
/** Now put some things into the memory for the other process to read. */
s = shm;
for (c = 'a'; c <= 'z'; c++)
{
*s++ = c;
}
*s = '\0';
/** Finally, we wait until the other process
* Changes the first character of our memory
* to '*', indicating that it has read what
* we put there.
*/
while (*shm != '*')
sleep(1);
printf("%c",*shm);
exit(0);
}
/* shm_client.c */
/*
* shm-client - client program to demonstrate shared memory.
*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <stdio.h>
#define SHMSIZE 27
main()
{
int shmid;
key_t key;
char *shm, *s;
/*
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 40
MC7404 NETWORK PROGRAMMING
UNIT – I
* We need to get the segment named * "5678", created by the server. */
key = 5678;
/* * Locate the segment. */
if ((shmid = shmget(key, SHMSIZE, 0666)) < 0) {
perror("shmget");
exit(1);
}
/* Now we attach the segment to our data space. */
if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
perror("shmat");
exit(1);
}
/* Now read what the server put in the memory. */
for (s = shm; *s != '\0'; s++)
putchar(*s);
putchar('\n');
/* * Finally, change the first character of the * segment to '*', in dicating we have
read * the segment. */
*shm = '*';
printf ("\nIts done from client.\n\n\n");
exit(0);
}
//output
Execute server first
//server
[root@localhost ~]# cc shmserver.c
[root@localhost ~]# ./a.out
4915214*[root@localhost ~]#
Client
[root@localhost ~]# cc shmclient.c
[root@localhost ~]# ./a.out
abcdefghijklmnopqrstuvwxyz
Its done from client.
[root@localhost ~]#
Characteristics of TCP
TCP also provides reliability.
TCP contains algorithms to estimate the round-trip time (RTT) between a
client and server dynamically so that it knows how long to wait for an
acknowledgment.
TCP also sequences the data by associating a sequence number with every
byte that it sends.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 41
MC7404 NETWORK PROGRAMMING
UNIT – I
TCP provides flow control. TCP always tells its peer exactly how many bytes
of data it is willing to accept from the peer at any one time. This is called the
advertised window.
TCP connection is full-duplex. This means that an application can send and
receive data in both directions on a given connection at any time.
TCP Connection Establishment and Termination
Three-Way Handshake
The following scenario occurs when a TCP connection is established:
1. The server must be prepared to accept an incoming connection. This is
normally done by calling socket, bind, and listen and is called a passive open.
2. The client issues an active open by calling connect. This causes the client
TCP to
send a "synchronize" (SYN) segment, which tells the server the client's initial
sequence number for the data that the client will send on the connection.
Normally, there is no data sent with the SYN; it just contains an IP header, a
TCP header, and possible TCP options.
3. The server must acknowledge (ACK) the client's SYN and the server must
also send its own SYN containing the initial sequence number for the data that
the server will send on the connection. The server sends its SYN and the ACK of
the client's SYN in a single segment.
4. The client must acknowledge the server's SYN.
The minimum number of packets required for this exchange is three; hence, this
is called TCP's three-way handshake.
TCP Three-way Handshake
TCP Connection Termination
While it takes three segments to establish a connection, it takes four to
terminate a connection.
1. One application calls close first, and we say that this end performs the active
close. This end's TCP sends a FIN segment, which means it is finished send ing
data.
2. The other end that receives the FIN performs the passive close. The received
FIN is acknowledged by TCP. The receipt of the FIN is also passed to the
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 42
MC7404 NETWORK PROGRAMMING
UNIT – I
application as an end-of-file (after any data that may have already been queued
for the application to receive), since the receipt of the FIN means the application
will not receive any additional data on the connection.
Packets exchanged when a TCP connection is closed
3. Sometime later, the application that received the end-of-file will close its
socket.
This causes its TCP to send a FIN.
4. The TCP on the system that receives this final FIN (the end that did the active
close) acknowledges the FIN.
Since a FIN and an ACK are required in each direction, four segments are
normally required. We use the qualifier "normally" because in some scenarios,
the FIN in Step 1 is sent with data. Also, the segments in Steps 2 and 3 are both
from the end performing the passive close and could be combined into one
segment.
Prepared by : Mrs. M.Nirmala / AP / MCA
Page : 43
Download