Você está na página 1de 119

COMPUTER NETWORKS 

LAB MANUAL

For 

VII SEMESTER 

COMPUTER SCIENCE

DEPARTMENT OF COMPUTER SCIENCE
People’s Education Society Institute Of technology

 
BANGALORE­ 560085

HARDWARE REQUIREMENTS

● Pentium IV , 1.2 GHz
● 40 GB HDD
● 256 MB RAM(Recommended 512 MB)
● Monitor
● Keyboard
● Mouse

SOFTWARE REQUIREMENTS

● Linux Kernel ver 2.6.9 (Fedora Core 3 or RHEL)
● NCTUns 2.0  Package
● gcc compiler

 
INTRODUCTION

Network   simulation   is   an   important   tool   in   developing,   testing   and 


evaluating network protocols. Simulation can be used without the target physical 
hardware, making it economical and practical for almost any scale of network 
topology and setup. It is possible to simulate a link of any bandwidth and delay, 
even if such a link is currently impossible in the real world. With simulation, it is 
possible to set each simulated node to use any desired software. This means that 
meaning deploying software is not an issue. Results are also easier to obtain and 
analyze, because extracting information from important points in the simulated 
network is as done by simply parsing the generated trace files. 

Simulation is only of use if the results are accurate, an inaccurate simulator 
is not useful at all. Most network simulators use abstractions of network protocols, 
rather than the real thing, making their results less convincing. S.Y. Wang reports 
that the simulator OPNET uses a simplified finite state machine to model complex 
TCP   protocol   processing.   [19]   NS­2   uses   a   model   based   on   BSD   TCP,   it   is 
implemented as a set of classes using inheritance. Neither uses protocol code that 
is used in real world networking.

 Improving Network Simulation:

 
Wang   states   that   “Simulation   results   are   not   as   convincing   as   those 
produced by real hardware and software equipment.” This statement is followed 
by   an   explanation   of   the   fact   that   most   existing   network   simulators   can   only 
simulate real life network protocol implementations with limited detail, which can 
lead to incorrect results. Another paper includes a similar statement, “running the 
actual TCP code is preferred to running an
abstract specification of the protocol.” Brakmo and Peterson go on to discuss how 
the   BSD   implementations   of   TCP   are   quite   important   with   respect   to   timers. 
Simulators often use more accurate round trip time measurements than those used 
in the BSD implementation, making results differ.
Using real world network stacks in a simulator should make results more 
accurate, but it is not clear how such stacks should be integrated with a simulator. 
The network simulator NCTUns shows how it is possible to use the network stack 
of the simulators machine.

Network Simulation Experience

The Network Simulator offers a simplified and complete network 
simulation experience. The following diagram depicts this functionality offered by 
the Network Simulator. 

 
The Network Simulator can design and simulate a network with SNMP, 
TL1, TFTF, FTP, Telnet and IOS devices, in four simple steps:

1. Add devices to the Device tree: Add devices with the required configuration to 
the device tree in the Network Designer. Preconfigured devices are also bundled 
with the toolkit.

2. Create the Network: Create and add bulk devices to the network, at one shot. 

3. Configure the Network devices: Configure the devices in the network, if 
required. 

4. Start the Network: Start the network or start individual agents in the network. 
The MIB Browser and TL1 Craft Interface test tools, can be used as the 
manager tools for testing.

Network Emulation

 
Network emulation refers to actual network traffic passing through some 
software which might do some analysis or perhaps modify the traffic in some way. 
The Emulation Network in the WAND group is used for testing and evaluation of 
networking   software   and   hardware.   The   scale   is   limited;   it   is   made   up   24 
emulation machines and one central controlling computer. Setup of such a network 
is time consuming and expensive: in addition to the aforementioned 25 computers, 
a Cisco 2950 switch and a Cyclades 32 port terminal server are included in the 
network. Each emulation machine also has a 4 port network interface controller. 
The controlling machine includes special capture cards (known as DAG [6] cards) 
to allow easier capture and processing of network traffic. This network has no easy 
way of adding latency and bandwidth bottlenecks, which means creating adverse 
conditions on the network is difficult. It is possible to use Dummynet  to
add latency, but this is a lot of work. There is a project to solve this issue; a non 
blocking crossbar Ethernet switch is being created for the network, but the cost 
involved is large.
Other network emulation done in the WAND group include validating the WAND 
simulator.   This   was   done   by   setting   up   a   physical   network   with   FreeBSD 
machines using Dummynet to add latency. Dummynet is one example of network 
emulation   software,   NIST   Net   is   another,   it   claims   to   “allow   controlled, 
reproducible   experiments   with   network   performance   sensitive/adaptive 
applications and control protocols in a simple laboratory setting”.

NS­2   also   provides   some   network   emulation   functionality,   it   is   able   to 


capture packets from the live network and drop, delay, re­order, or duplicate them. 
Emulation, especially in the case of a network simulator like NS­2, is interesting 
because it is using real world  data from real world network stacks. Emulation 
offers something simulation never can: it is performed on a real network, using 
actual   equipment   and   real   software.   However,   it   is   very   limited   compared   to 
simulation   in   other   areas;   for   example   scale.   The   WAND   Emulation   Network 
described earlier requires a lot of setup and is expensive, yet only contains 24 
emulation   machines.   There   is   no   theoretical   limit   to   the   number   of   nodes   a 
simulator   can   handle,   and   increasing   the   size   of   a   simulation   does   not   cost 
anything. The factors to consider are RAM, disk space and the small amount of 
time taken to change a simulation script. In general, changing the simulation is a 
simple step, though it would be complex in the case a huge amount of nodes being 
required (a million, for example).

Also,   network   emulation   must   of   course   be   run   in   real   time,   where 


simulation can sometimes simulate large time periods in a small amount of time. 

 
In the case of a million nodes, the simulation might run in greater than real time 
because the hardware it is run on     would limit performance.

Introduction to Network Simulators

Network   simulators   implemented   in   software   are   valuable   tools   for 


researchers   to   develop,   test,   and   diagnose   network   protocols.   Simulation   is 
economical because it can
carry out experiments without the actual hardware. It is flexible because it can, for 
example, simulate a link with any bandwidth and propagation delay. Simulation 
results
are easier to analyze than experimental results because important information at 
critical points can be easily logged to help researchers diagnose network protocols.

Network simulators, however, have their limitations. A complete network 
simulator   needs   to   simulate   networking   devices   (e.g.,   hosts   and   routers)   and 
application   programs   that   generate   network   traffic.   It   also   needs   to   provide 
network   utility   programs   to   configure,   monitor,   and   gather   statistics   about   a 
simulated network. Therefore, developing a complete network simulator is a large 
effort.   Due   to   limited   development   resources,   traditional   network   simulators 
usually have the following drawbacks:

• Simulation results are not as convincing as those produced by real hardware and 
software equipment. In order to constrain their complexity and development cost, 
most   network   simulators   usually   can   only   simulate   real­life   network   protocol 
implementations with limited details, and this may lead to incorrect results. 

• These simulators are not extensible in the sense that they lack the standard UNIX 
POSIX   application   programming   interface   (API).   As   such,   existing   or   to­be­
developed real­life application programs cannot run normally to generate traffic 
for a simulated network. Instead, they must be rewritten to use the internal API 
provided by the simulator (if there is any) and be compiled with the simulator to 
form a single, big, and complex program. 

To   overcome   these   problems,   Wang   invented   a   kernel   re­entering 


simulation methodology and used it to implement the Harvard network simulator. 
Later   on,   Wang   further   improved   the   methodology   and   used   it   to   design   and 

 
implement the NCTUns network simulator and emulator.

Different types of simulators

Some of the different types of simulators are as follows:­

● MIT's NETSIM 
● NIST 
● CPSIM 
● INSANE 
● NEST 
● REAL 
● NS 
● OPNET
● NCTUns

A brief explanation of some of the above simulators is as follows:­

REAL 

REAL   (REalistic   And   Large)   is   a   network   simulator   written   at   Cornell 


University by S. Keshav and based on a modified version of NEST 2.5. 

Use

NEST   is   intended   for   studying   the   dynamic   behavior   of   flow   and 


congestion control schemes in packet­switched data networks (namely TCP/IP). 

The package

REAL   provides   30   modules   written   in   C   that   emulate   flow­control 


protocols such as TCP, and 5 scheduling disciplines such as FIFO, Fair Queuing, 
DEC congestion avoidance and Hierarchical Round Robin. 

The description of the network topology, protocols workload and control 
parameters   are   transmitted   to   the   server   using   a   simple   ASCII   representation 
called NetLanguage where the network is modeled as a graph. This latest release 
now includes a GUI written in Java. 

 
Implementation of the simulator

The NEST code has been rewritten to make it less general, cleaner and faster. 
REAL is still implemented as a client­server program. The code is freely available 
to anyone willing to modify it. Node functions implement computation at each 
node in the network whereas queue management and routing functions manage 
buffers in nodes and packet switching. Routing is static and is based on Dijkstras's 
shortest path algorithm. A node could be a source, a router or a sink. Source nodes 
implement   TCP­like   transport   layer   functionality.   Routers   implement   the 
scheduling   disciplines,   while   the   sinks   are   universal   receivers   that   only 
acknowledge packets. 

Since NEST didn't not allow for timers, REAL sends out a timer packet 
from a source back to itself to return after some specified time, but timers cannot 
be reset using this method.

NS version 2.0

NS  is   a   object­oriented   discrete­event  simulator   for  networking   research 


based on REAL. Initially, NS version 1.0 was developed by the Network Research 
Group at the Lawrence Berkeley National Laboratory (LBNL). Its development is 
now part of the VINT project under which NS version 2.0 was released.

Use

At the time being, NS is well suited for packets switched networks and is 
used mostly for small­scale simulations of queuing algorithms, transport protocol 
congestion   control,   and   some   multicast   related   work.   It   provides   support   for 
various implementations of TCP, routing, multicast protocols, link layer, MAC, ... 
It currently has memory limitations in the face of large simulations. 

The package

The current non­beta version of NS implements key protocol modules for 
unicast and multicast routing, reservation, transport and session protocols. NS is 
written   in   C++.   The   package   provides   a   compiled   class   hierarchy   of   objects 
written in C++ and an interpreted class hierarchy of objects written in OTcl (MIT's 
object extension to Tcl ­ Tool Command Language), which are closely related to 

 
the compiled ones. The user creates new objects through the OTcl interpreter. New 
objects are closely mirrored by a corresponding object in the compiled hierarchy. 

Tcl procedures are used to provide flexible and powerful control over the 
simulation (start and stop events, network failure, statistic gathering and network 
configuration). The Tcl interpreter has been extended (OTcl) with commands to 
create the networks topology of links and nodes and the agents associated with 
nodes. 

Implementation of the simulator 

The simulation is configured, controlled and operated through the use of 
interfaces provided by the OTcl class Simulator. The class provides procedure to 
create and manage the topology, to initialize the packet format and to choose the 
scheduler. It stores internally references to each element of the topology. The user 
creates the topology using OTcl through the use of the standalone class node and 
link that provide a few simple primitives. 

The function of a node is to receive a packet, to examine it and map it to the 
relevant outgoing interfaces. A node is composed of simpler classifier objects. 
Each   classifier   in   a   node   performs   a   particular   function,   looking   at   a   specific 
portion of the packet and forwarding it to the next classifier. 

An agent is another type of components of a node: those model endpoints 
of the network where packets are fed or consumed. Users create new sources or 
sinks from the class Agent. NS currently supports various TCP agents, CBR, UDP, 
and others protocols, including RTP, RTCP, SRM. There is no mention of ATM 
protocols. 

Links are characterized in terms of delay and bandwidth. They are built 
from a sequence of connectors objects. The data structure representing a link is 
composed by a queue of connector objects, its head, the type of link, the ttl (time 
to   live),   and   an   object   that   processes   link   drops.   Connectors   receive   packet, 
perform a function, and send the packet to the next connector or to the drop object. 
Various kinds of links are supported, e.g. point­to­point, broadcast, wireless. 

The output buffers attached to a link in a ``real'' router in a network are 
modeled by queues. In NS, queues are considered as part of a link. NS allows the 
simulation   of   various   queuing   and   packet   scheduling   disciplines.   C++   classes 

 
provided include drop­tail (FIFO) queuing, Random Early Detection (RED) buffer 
management, CBQ (priority  and round robin),  Weighted Fair Queuing (WFQ), 
Stochastic Fair Queuing (SFQ) and Deficit Round­Robin (DRR). 

Traffic generation in NS looks rather basic in the current implementation. 
For the purpose of TCP, only FTP and Telnet traffic can be generated; otherwise, 
NS provides an exponential on/off distribution and it allows to generate traffic 
according to a trace file. 

In order to analyze results, NS provides classes to trace each individual 
packet   as   it   arrives,   departs   or   is   dropped,   and   to   record   any   kind   of   counts, 
applied on all packets or a per­flow basis. The trace can be set or unset as desired 
by the user. 

The user has to specify the routing strategy (static, dynamic) and protocol 
to be used. This is done with a procedure in the class simulator. Supported routing 
features   include   asymmetric   routing,   multipath   routing,   Distance   Vector 
algorithm, multicast routing (PIM, ...). 

Other features of NS include error models where the unit could be packet, 
bit or time based, and mathematical classes for the approximation of continuous 
integration by discrete sums and for random number generation (implementation 
of the minimal standard multiplicative linear congruential generator of Park et al). 
In order to verify some aspects of the protocol to be simulated, NS includes some 
validation tests distributed with the simulator. Is as well includes capabilities to 
make   the   simulation   topologies   dynamic   although   this   latest   point   is   still 
somewhat experimental. 

OPNET

OPNET (Optimized Network Engineering Tools) is a commercial tool from 
MIL3 Inc. It is being developed for almost 15 years. 

Use 

Network with several hundreds of nodes can be simulated, but it would take 
time for the computation. Companies like Thomson­CSF or CNET, which use it to 

 
model ATM networks and validate various layers protocols, use OPNET, packet 
switched radio networks. 

The package 

The   software   comprises   several   tools   and   is   divided   in   several   parts, 


OPNET Modeler and OPNET Planner, the Model Library, and the Analysis tool. 
Features   included   in   this   generic   simulator   are   an   event­driven   scheduled 
simulation kernel, integrated analysis tools for interpreting and synthesizing output 
data, graphical specification of models and a hierarchical object­based modeling.. 

OPNET Modeler is intended for modeling, simulating and analyzing the 
performance   of   large   communications   networks,   computer   systems   and 
applications.   Common   uses   are   assessing   and   feasibility   of   new   designs, 
optimizing   already   developed   communication   systems   and   predicting 
performance. 

The   modeling   methodology   of   OPNET   is   organized   in   a   hierarchical 


structure.   At   the   lowest   level,   process   models   are   structured   as   a   finite   state 
machine.   State   and   transitions   are   specified   graphically   using   state­transition 
diagrams   whereas   conditions   that   specify   what   happen   within   each   state   are 
programmed with a C­like language called Proto­C. Those processes, and built­in 
modules   in   OPNET   (source   and   destination   modules,   traffic   generators, 
queues, ...) are then configured with menus and organized into data flow diagrams 
that represent nodes using the graphical Node Editor. Using a graphical Network 
Editor, nodes and links are selected to build up the topology of a communication 
network. 

The   Analysis   Tool   provides   a   graphical   environment   to   view   and 


manipulate data collected during simulation runs. Results can be analyzed for any 
network element. 

OPNET Planner is an application that allows administrators to evaluate the 
performance   of   communications   networks   and   distributed   systems,   without 
programming   or   compiling.   Planner   analyses   behavior   and   performance   by 
discrete­event simulations. Models are built using a graphical interface. The user 
only chooses pre­defined models (from the physical layer to the application) from 
the   library   and   sets   attributes.   The   user   cannot   define   new   models;   he   should 
contact MIL3's modeling service. 

 
The   modeling   libraries   are   included   with   OPNET   Modeler   and   OPNET 
Planner   and   contains   protocols   and   analysis   environments,   among   them   ATM, 
TCP, IP, Frame Relay, FDDI, Ethernet, link models such as point­to­point or bus, 
queuing   service   disciplines   such   as   First­in­First­Out   (FIFO),   Last­In­First­Out 
(LIFO),   priority   non­preemptive   queuing,   shortest   first   job,   round­robin   or 
preempt and resume. 

In the ATM library, 16 processes models implement the functions of ATM, 
the   AAL   and   the   IP   interface.   It   provides   for   buffer   management,   congestion 
control,   segmentation   and   reassembly,   modeled   explicitly   or   analytically.   The 
ATM library can be used for instance to model and evaluate Adaptation Layer 
(AAL) protocols; or to analyze the behavior of virtual path and circuits under 
various best effort congestion control schemes at the physical layer 

In the IP library, interfaces to other protocols such as ATM or Ethernet are 
provided.

NCTUns

Introduction

NCTUns   is   open   source,   high   quality,   and   supports   many   types   of 
networks.The   NCTUns  is  a high­fidelity   and  extensible  network   simulator  and 
emulator capable of simulating various protocols used in both wired and wireless 
IP   networks.   Its   core   technology   is   based   on   the   novel   kernel   re­entering 
methodology invented by Prof. S.Y. Wang [1, 2] when he was pursuing his Ph.D. 
degree at Harvard University. Due to this novel methodology, NCTUns provides 
many unique advantages that cannot be easily  achieved  by traditional  network 
simulators such as ns­2 [3] and OPNET [4]. 

After  obtaining   his  Ph.D.  degree  from  Harvard   University   in  September 
1999, Prof. S.Y. Wang returned to Taiwan and became an assistant professor in 
the   Department   of   Computer   Science   and   Information   Engineering,   National 
Chiao Tung University (NCTU), Taiwan, where he founded his “Network and 
System   Laboratory.”   Since   that   time,   Prof.   S.Y.   Wang   has   been   leading   and 
working with his students to design and implement NCTUns (the NCTU Network 
Simulator) for more than five years.  

 
Salient features of NCTUns 

The   NCTUns   network   simulator   and   emulator   has   many   useful   features 
listed as follows: 

● It can be used as an emulator. An external host in the real world can exchange 
packets (e.g., set up a TCP connection) with nodes (e.g., host, router, or mobile 
station) in a network simulated by NCTUns. Two  external hosts in the real 
world can also exchange their packets via a network simulated by NCTUns. 
This   feature   is   very   useful   as   the   function   and   performance   of   real­world 
devices can be tested under various simulated network conditions.

● It directly uses the real­life Linux ’s TCP/IP protocol stack to generate high­
fidelity   simulation   results.   By   using   a   novel   kernel   re­entering   simulation 
methodology,   a   real­life   UNIX   (e.g.,   Linux)   kernel’s   protocol   stack   can   be 
directly used to generate high­fidelity simulation results.

● It can use any real­life existing or to­be­developed UNIX application program 
as a traffic generator program without any modification. Any real­life program 
can be run on a simulated network to generate network traffic. This enables a 
researcher to test the functionality and performance of a distributed application 
or system under various network conditions. Another important advantage of 
this feature is that application programs developed during simulation studies 
can   be   directly   moved   to   and   used   on   real­world   UNIX   machines   after 
simulation studies are finished. This eliminates the time and effort required to 
port   a   simulation   prototype   to   a   real­world   implementation   if   traditional 
network simulators are used.

● It can use any real­life UNIX network configuration and monitoring tools. For 
example, the UNIX route, ifconfig, netstat, tcpdump, traceroute commands can 
be run on a simulated network to configure or monitor the simulated network. 

● In   NCTUns,   the   setup   and   usage   of   a   simulated   network   and   application 


programs are exactly the same as those used in real­world IP networks. For 
example, each layer­3 interface has an IP address assigned to it and application 
programs directly use these IP addresses to communicate with each other. For 
this reason, any person who is familiar with real­world IP networks can easily 
learn and operate NCTUns in a few minutes. For the same reason, NCTUns can 

 
be used as an educational tool to teach students how to configure and operate a 
real­world network.  

● It can simulate fixed Internet, Wireless LANs, mobile ad hoc (sensor) networks, 
GPRS networks, and optical networks. A wired network is composed of fixed 
nodes and point­to­point links. Traditional circuit­switching optical networks 
and   more   advanced   Optical   Burst   Switching   (OBS)   networks   are   also 
supported. A wireless networks is composed of IEEE 802.11 (b) mobile nodes 
and   access   points   (both   the   ad­hoc   mode   and   infra­structure   mode   are 
supported). GPRS cellular networks are also supported.

● It   can   simulate   various   networking   devices.   For   example,   Ethernet   hubs, 


switches, routers, hosts, IEEE 802.11 (b) wireless stations and access points, 
WAN   (for   purposely   delaying/dropping/reordering   packets),   Wall   (wireless 
signal obstacle), GPRS base station, GPRS phone, GPRS GGSN, GPRS SGSN, 
optical circuit switch, optical burst switch, QoS DiffServ interior and boundary 
routers, etc. 

● It can simulate various protocols. For example, IEEE 802.3 CSMA/CD MAC, 
IEEE   802.11   (b)   CSMA/CA   MAC,   learning   bridge   protocol,   spanning   tree 
protocol,   IP,   Mobile   IP,   Diffserv   (QoS),   RIP,   OSPF,   UDP,   TCP, 
RTP/RTCP/SDP, HTTP, FTP, Telnet, etc. 

● Its simulation speed is high. By combining the kernel re­entering methodology 
with   the   discrete­event   simulation   methodology,   a   simulation   job   can   be 
finished quickly.

● Its simulation results are repeatable. If the chosen random number seed for a 
simulation case is fixed, the simulation results of a case are the same across 
different simulation runs even though there are some other activities (e.g., disk 
I/O) occurring on the simulation machine.

● It provides a highly integrated and professional GUI environment. This GUI 
can help a user (1) draw network topologies, (2) configure the protocol modules 
used   inside   a   node,   (3)  specify   the   moving   paths   of  mobile   nodes,   (4)  plot 
network performance graphs, (5) playing back the animation of a logged packet 
transfer trace, etc. All these operations can be easily and intuitively done with 
the GUI. 

 
● Its simulation engine adopts an open­system architecture and is open source. By 
using   a   set   of   module   APIs   provided   by   the   simulation   engine,   a   protocol 
module writer can easily implement his (her) protocol and integrate it into the 
simulation engine. NCTUns uses a simple but effective syntax to describe the 
settings and configurations of a simulation job. These descriptions are generated 
by the GUI and stored in a suite of files. Normally the GUI will automatically 
transfer   these   files   to   the   simulation   engine   for   execution.   However,   if   a 
researcher wants to try his (her) novel device or network configurations that the 
current GUI does not support, he (she) can totally bypass the GUI and generate 
the suite of description files by himself (herself) using any text editor (or script 
program). The non­GUI­generated suite of files can then be manually fed to the 
simulation engine for execution.    

● It supports remote and concurrent simulations. NCTUns adopts a distributed 
architecture. The GUI and simulation engine are separately implemented and 
use the client­server model to communicate. Therefore, a remote user using the 
GUI program can remotely submit his (her) simulation job to a server running 
the simulation engine. The server will run the submitted simulation job  and 
later   return   the   results   back   to   the   remote   GUI   program   for   analyzes.   This 
scheme   can   easily   support   the   cluster­computing   model   in   which   multiple 
simulation jobs are performed in parallel on different server machines. This can 
increase the total simulation throughput.

● It supports  more realistic  wireless signal propagation  models.  In addition  to 


providing the simple (transmission range = 250 m, interference range = 550 m) 
model that is commonly used in the ns­2, NCTUns provides a more realistic 
model   in   which   a   received   bit’s   BER   is   calculated   based   on   the   used 
modulation scheme, the bit’s received power level, and the noise power level 
around the receiver. Large­scale path loss and small­scale fading  effects are 
also simulated.

The different versions of NCTUns

● NCTUns 1.0 simulator
● NCTUns 2.0 simulator

 
NCTUns 1.0 simulator 

The NCTUns 1.0 network simulator is a successor to the Harvard network 
simulator.   The   NCTUns   1.0   is   a   high   fidelity   and   extensible   discrete   event 
network simulator capable of simulating various protocols used in both wired and 
wireless   IP   networks.   Its   core   technology   is   based   on   a   kernel   reentering 
simulation methodology. In NCTUns 1.0, real­world TCP/IP protocol stacks are 
directly used to generate accurate simulation results, and all real­world application 
programs can directly run on any network simulated by this tool. 

           The NCTUns 1.0. is equipped with a GUI environment to help a user to 
quickly (1) specify network topologies, (2) edit protocol parameters, (3) control 
the execution of simulations, (4) plot logged performance curves, and (5) play 
back logged packet transfer animations. It uses a distributed architecture to support 
remote   and   concurrent   simulations   on   multiple   machines.   A   user   can   just 
download the GUI program, use it to specify his (her) simulation job, and then 
submit   the   job   to   a   remote   simulation   server   for   execution.   When   the   job   is 
finished, the results will be automatically transferred back to the GUI program for 
further analysis. NCTUns' simulation engine uses an open system architecture to 
allow a user to easily add protocol modules. Adding a new protocol module into 
an existing protocol stack of a node or replacing an old one with a new one can be 
done via the GUI program's node editor. 

       Due to the kernel reentering simulation methodology, NCTUns 1.0 needs to 
modify the kernel of the underlying operating system. Right now only FreeBSD 
4.7 and 4.6 are supported; however, porting the simulator to the Linux platform is 
underway. The NCTUns 1.0 is written in C++. It is open source, free for nonprofit 
use,   and   has   an   active   user   community.   The   Web   site   provides   the   package, 
documentation   (papers,   GUI   user   manual,   and   protocol   module   developer 
manual), demo videos, mailing lists, and a free simulation center service.

NCTUns 1.0 is a simulator, which attempts to make use of a real world 
network stack for simulation. NCTUns uses a tunnel network interface to use the 
local   machines   network   stack.   Tunnel   devices   are   available   on   most   UNIX 

 
machines and allow packets to be written to and read from a special device file. To 
the kernel, it appears as though packets have arrived from the link layer when data 
is written to the device file. This means the packet will go through all the normal 
processing   routines: the   TCP/IP  stack.   When   a  packet  is  read  from   the   tunnel 
device,   the   first   packet   in   the   tunnel   interfaces   output   queue   is   copied   to   the 
reading application.

The first obvious problem with this is that timing is still handled by the 
kernel,   and   hence   there   is   no   simulated   time.   This   is   solved   in   NCTUns   by 
modifying the kernel to use a special virtual timer. The virtual time resides in a 
memory­mapped region accessible both to kernel and user space. The kernel code 
is modified, which has negative repercussions. First of all, each kernel NCTUns 
might run on needs to be patched. This means that for every differing version of 
each operating system, a patch needs to be written. Secondly, the kernel needs to 
be patched on all simulation machines. This is not always an option, especially in 
a laboratory setting where the users do not often have full control of the computers 
available. One of the problems discussed in the NCTUns 1.0 paper [19] is that of 
performance. Because of the real network code being executed, abstractions of 
stacks cannot be executed: there is more processing necessary
in a real stack. Real data is transferred throughout the system and also needs to be 
copied. To some extent this problem would apply to a real network stack used 
inside   the   Network   Simulation   Cradle,   as   it   would   need   the   actual   data   to   do 
packet processing on too. The Network Simulation Cradle only needs the packet 
headers, the entire packets do not need to be used. A lot of system calls are needed 
in NCTUns’s case, which also reduces performance. Even with these issues Wang 
concludes,   the   performance   of   the   NCTUns   1.0   in   its   current   form   is   still 
satisfactory”. NCTUns achieved reasonably scalability ­ more than 256 nodes ­ by 
working around an initial limitation imposed by BSD UNIX, due to 8­bit integers 
being used to identify devices. Other problems with NCTUns include the fact that 
it is difficult to get statistics out of the stack code running inside the kernel, and 
only one stack type is used in simulation. Other stacks could be used in NCTUns 
by a distributed simulation approach, but this requires at least one machine per 
stack simulated, each running the specific operating system version wanting to be 
simulated. This means the simulation is more like an emulation, which loses some 
of the benefits  of simulation.  Also, because the  simulation  network  stacks run 
inside the kernel, the simulation computer cannot be used for other activities while 
simulating, such activity could make the kernel behave quite differently.

 
GETTING STARTED

 
Setting up the environment
     
A   user   using   the   NCTUns   in   single   machine   mode,   needs   to   do   the 
following steps before he/she starts the GUI program:

1.   Set up environment variables:
  Before the user can run up the dispatcher, coordinator, or NCTUns GUI  
  program he/she must set up the NCTUNSHOME environment variable.        

2.   Start up the dispatcher on terminal 1.

3.   Start up the coordinator on terminal 2.

4.   Start up the nctunsclient on terminal 3.

After the above steps are followed, the starting screen of NCTUns disappears and 
the user is presented with the working window as shown below:

Drawing A Network Topology

 
To draw a new network topology, a user can perform the following steps:

Choose Menu­>File­>Operating Mode­> and make sure that the “Draw Topology” 
mode is checked. This is the default mode of NCTUns when it is launched. It is 
only in this mode that a user can draw a new network topology or change an 
existing simulation topology. When a user switches the mode to the next mode “ 
Edit Property”, the simulation network topology can no longer be changed.

1. Move the cursor to the toolbar.

2. Left­Click the router icon on the toolbar.

3. Left­Click anywhere in the blank working area to add a router to the current 
network   topology.   In   the   same   way   we   can   add   switch,   hub,WLAN   access 
point,WLAN mobile node , wall (wireless signal obstacle) etc.

4. Left­Click the host icon on the toolbar. Like in step 4, add the required number 
of hosts to the current topology. 

5. To add links between the hosts and the router, left­click the link icon on the 
toolbar to select it.

6. Left­Click a host and hold the mouse button. Drag this link to the router and 
then release the mouse left button on top of the router. Now a link between the 
selected host and the router has been created.

7. Add the other, required number of links in the same way. This completes the 
creation of a simple network topology.

8. Save this network topology by choosing Menu­>File­>Save. It is saved with a
.tpl extension.
9.  Take the snapshot of the above topology.

 
Editing Node's Properties

1. A network node (device) may have many parameters to set. For example, we 
may have to set the maximum bandwidth, maximum queue size etc to be used 
in a network interface. For another example, we may want to specify that some 
application programs (traffic generators) should be run on some hosts or routers 
to generate network traffic.

2. Before a user can start editing the properties of a node, he/she should switch the 
mode   from   the   “Draw   Topology”   to   “Edit   Property”   mode.   In   this   mode, 
topology changes can no longer be made. That is, a user cannot add or delete 
nodes or links at this time.

3. The GUI automatically finds subnets in a network and generates and assigns IP 
and MAC addresses to layer 3 network interfaces.

4. A user should be aware that if he/she switches the mode back to the “Draw 
Topology”   mode   when   he/she   again   switches   the   mode   back   to   the   “Edit 
Topology”   mode,   node's   IP   and   MAC   addresses   will   be   regenerated   and 
assigned to layer 3 interfaces. Therefore the application programs now may use 
wrong IP addresses to communicate with their partners.

 
Running the Simulation

When a user finishes editing the properties of network nodes and specifying 
application programs to be executed during a simulation, he/she can start running 
the simulation.

2. In order to do so, the user must switch mode explicitly from “Edit Property” to 
“Run   Simulation”.   Entering   this   mode   indicates   that   no   more   changes   can 
(should) be made to the simulation case, which is reasonable. This simulation is 
about to be started at this moment; of course, any of its settings should be fixed.

3. Whenever   the   mode   is   switched   to   the   “   Run   Simulation”   mode,   the   many 
simulation files that collectively describe the simulation case will be exported. 
These   simulation   files   will   be   transferred   to   the   (either   remote   or   local) 
simulation server for it to execute the simulation. These files are stored in the “ 
main   File   Name.sim”   directory,   where   main   Filename   is   the   name   of   the 
simulation case chosen in the “Draw Topology” mode.

Playing Back the Packet Animation Trace

After   the   simulation   is   finished,   the   simulation   server   will   send   back   the 
simulation  result files  to the  GUI program after receiving  these  files,  the GUI 
program will store these files in the “results directory” .It will then automatically 
switch to “play back mode”.

1. These files include a packet animation trace file and all performance log files 
that the user specifies to generate. Outputting these performance log files can be 
specified by checking some output options in some protocol modules in the 
node editor. In addition to this, application programs can generate their own 
data files.
3. The packet animation trace file can be replayed later by the packet animation 
player. The performance curve of these log files can be plotted by the performance 
monitor.

 
Post Analysis

1. When the user wants to review the simulation results of a simulation case that 
has been finished before, he /she can run up the GUI program again and then open 
the case's topology file

2. The  user can switch the mode  directly  to the  “Play Back”  mode.  The GUI 


program will then automatically reload the results (including the packet animation 
trace file and performance log file.

3. After   the   loading   process   is   finished,   the   user   can   use   the   control   buttons 
located at the bottom of the screen to view the animation.

Simulation Commands

The following explains the meaning of each job control command:

●   Run: Start to run the simulation.

●  Pause: Pause the currently ­running simulation.

●  Continue: Continue the simulation that was just paused.

●  Stop: Stop the currently ­running simulation

● Abort: Abort the currently running simulation. The difference between “stop” 
and “abort” is that a stopped simulation job's partial results will be transferred 
back to GUI files.

 
● Reconnect:   The   Reconnect   command   can   be   executed   to   reconnect   to   a 
simulation   job   that   was   previously   disconnected.   All   disconnected   jobs   that 
have not finished their simulations or have finished their simulations but the 
results  have  not  been  retrieved   back  to  be  a  GUI  program by  the  user  will 
appear in a session table next to the “Reconnect” command. When executing 
the reconnect command, a user can choose a disconnected job to reconnect from 
this session table.

● Disconnect:   Disconnect the GUI from the currently running simulation job. 
The GUI now can be used to service another simulation job. A disconnected 
simulation will be given a session name and stored in a session table.

PART­A

 
EXPERIMENT 1

Simulate a three­node point­to­point network with a duplex link 
between them. Set the queue size and vary the bandwidth and find the 
number of packets dropped.

STEPS:

Step1:  Select the hub icon on the toolbar and drag it onto the working window.

Step2: Select the host icon on the toolbar and drag it onto the working window. 
Repeat this for another host icon.

Step 3: Select the link icon on the toolbar and drag it on the screen from host 
(node 1) to the hub and again from host(node 2) to the hub. Here the hub acts as
node 3 in the point­to­point network. This leads to the creation of the 3­ 
           node point­to­point network topology. Save this topology as a .tpl file.

Step 4:Double­click on host(node 1), a host dialog box will open up. Click on  
Node editor and you can see the different layers­ interface, ARP,                  

 
           FIFO, MAC, TCPDUMP, Physical layers. Select MAC and then select full­ 
           duplex for switches and routers and half duplex for hubs, and in log             
           Statistics, select Number of Drop Packets, Number of Collisions,  
           Throughput of incoming packets and Throughput of outgoing packets.  
           Select FIFO and set the queue size to 50 and press OK. Then click on   
           Add. Another dialog box pops up. Click on the Command box and type the 
           Command according to the following syntax:

   stg [­t   duration(sec)] [­p port number]HostIPaddr
and click OK.

Step 5: Double­click on host (node 2), and follow the same step as above with 
only    change in command according to the following syntax:
                                                rtg [­t] [­w log]  [­p port number]
   and click OK.

Step 6: Double click on the link between node 1 and the hub to set the bandwidth 
  to some initial value say, 10 Mbps. Repeat the same for the other node.

Step 7: Click on the E button (Edit Property) present on the toolbar in order to 
save    the changes made to the topology. Now click on the R button (Run
Simulation). By doing so a user can
run/pause/continue/stop/abort/disconnect/reconnect/submit 
             a simulation. No simulation settings can be changed in this mode.

Step 8: Now go to Menu­>Simulation­>Run. Executing this command will submit 
  the   current   simulation   job   to   one   available   simulation   server  
managed by the dispatcher. When the simulation server is executing, the  
user will see the time knot at the bottom of the screen move. The time knot 
reflects the current virtual time (progress) of the simulation case. 

Step 9:To start the playback, the user can left­click the start icon( |>) of the time 
bar located at the bottom. The animation player will then start playing the 
recorded packet animation.

Step 10: Change the bandwidth say, 9 Mbps, and run the simulation and compare 
    the two results.

Step 12: To view the results, go to the filename. results folder.

 
Note:  To get the syntax of any command, double click on the host icon. Host 
dialog boxes appear and then choose App. Usage. 

The screenshot below explain the topology.

 
EXAMPLE AND RESULTS OF EXPT 1

By using HUB:

 
Commands used:  stg ­u 1024  100 1.0.1.2
                          rtg ­u ­w log1

 By setting the bandwidth as 10 Mbps on both the links and queue size as 50  we 
obtain the following results:

    Output throughput    n1­p1= 1177
   
                Input throughput n3­p1 = 1177

    Collision and drop = 0

By changing bandwidth to 9Mbps in the destination link, we obtain the following 
results:

    Output throughput n1­p1 =1177

              Input throughput n3­p1 = ~ 0

                       Collision and drop = 1100

Note: The results of the experiments vary from simulation to    
  simulation.

By using SWITCH

 
Commands used:  stcp ­p 7000 ­l 1024 1.0.1.2
                          rtcp ­p 7000 ­l 1024

Results: By setting the bandwidth as 10 Mbps  on both the links and queue size as 
50  we obtain the following results:

   output throughput    n1­p1= 1190

   input throughput  n3­p1 = 1190

   collision and drop = 0

By changing bandwidth to 9Mbps in the destination link, we obtain the following 
results:

   output throughput n1­p1 =1190

               input throughput n3­p1 = varying

   collision and drop = ~0

 
EXPERIMENT 2

Simulate a four­node point­to­point network and connect the link as 
follows: Apply a TCP agent between n0 to n3 and apply a UDP agent between 
n1 and n3. Apply relevant applications over TCP and UDP agents changing 
the parameters and determine the number of packets sent by two agents.

STEPS:

Step 1:  Create the topology as specified in the question, in the draw mode of   
  the simulator.

Step 2:  Go to edit mode and save the topology.

Step 3: Setup a TCP connection between node 1 and node 3 using the following 
  commands:
stcp [­p port] [­l writesize] hostIPaddr
rtcp [­p port] [­l readsize] 

Step 4: Setup a UDP connection between node 2 and node 3 using the following 
 commands:

stg [­u payload size duration] [Hostaddress]
rtg [­u] [­w log]

Step 5:Set the output throughput log to determine the number of packets sent by 
TCP/UDP as described in experiment 1.

Step 6:To view the results, go to the filename.results folder.

 
The screenshot of the topology is shown below:

 
EXAMPLE AND RESULTS OF EXPT 2

Commands used:  stg ­u 1024 100 1.0.1.3
                          rtg ­u ­w log1
                         stcp ­p 7000 ­l 1024 1.0.1.3
                         rtcp ­p 7000 ­l 1024

Results: By setting the bandwidth as 100 Mbps on the TCP link and queue size as 
50  we obtain the following results:

 Average no: of TCP packets sent = varying (348 to 1100)
 Average no: of UDP packets sent = 1180

Note: The result varies based on the bandwidth.

 
EXPERIMENT 3

Simulate the different types of Internet traffic such as FTP, TELNET 
over a network and analyze the throughput.

STEPS :

To setup a FTP connection:

Step 1:  Create a topology of four nodes; connect these nodes to a hub.

Step 2: Go to the edit mode and setup FTP traffic between node1 and node 4 
  using the port number 23.

Step 3:  Set the input and output throughput log file as described in the above 
   experiments.

Step 4: To view the results, go to the filename.results folder.

To setup a TELNET connection:

Step 1:  Create a topology of four nodes, connect these nodes to a hub.

Step 2: Go to the edit mode and setup a TELNET traffic between node1 and node 
  4  using the port number 7300.

Step 3:  Set the input and output throughput log file as described in the above 

 
   experiments.

Step 4: To view the results, go to the filename.results folder.

The screenshot of the topology is shown below: 

 
EXAMPLE AND RESULTS OF EXPT 3

Result:

For FTP:

Command used: stcp ­p 23 ­l 1024 1.0.1.6
      rtcp ­p 23 ­l 1024

 
 

Output Throughput n1­ p1= 680­1097

Input Throughput    n2­p1 = 680­1097

For TELNET:

Command used: stcp ­p 7300 ­l 1024 1.0.1.6
                           rtcp ­p  7300 ­l 1024

Output Throughput n1­p1= 495­1095

Input Throughput     n2­p1= 495­1095
 

EXPERIMENT 4

Simulate the transmission of ping messages over a network topology 
consisting   of   6   nodes   and   find   the   number   of   packets   dropped   due   to 
congestion.

 
STEPS:

Step 1: Click on the subnet icon on the toolbar and then click on the screen of the 
  working window.

Step 2:  Select the required number of hosts and a suitable radius between the host 
   and the switch.

Step 3:  In the edit mode, get the IP address of one of the hosts say, host 1 and then 
  for the other host say, host2 set the drop packet and no: of collisions    
   statistics as described in the earlier experiments.

Step 4: Now run the simulation.

Step 5: Now click on any one of the hosts and click on command console and 
   ping the destination node.

Note: The no: of drop packets are obtained only when the traffic is more in the   
network.  

The screenshot of the topology is shown below:

 
EXAMPLE  AND RESULTS OF EXPT 4

 
Results:

1) No need to setup any commands on the node editor.

             2) During Run mode open command console and ping 1.0.1.6.

 
EXPERIMENT 5

Simulate an Ethernet LAN using N nodes (6­10), change error rate and 
data rate and compare throughput.

STEPS:

 Step 1: Connect one set of hosts with a hub and another set of hosts also through a 
  hub and connect these two hubs through a switch. This forms an Ethernet 
  LAN.

 Step 2:  Setup a TCP connection between a host on one hub and host on another 
   hub using the following command:

stcp [­p port] [­l writesize] hostIPaddr
rtcp [­p port] [­l readsize] 

Step 3: Setup the error rate, data rate in the physical layer, input and output 
throughput in the mac layer as described above.

Step 4:Change error rate and data rate and compare the throughputs.

Step 5: View the results in the filename.results.

 
The screenshot of the topology is shown below:

 
EXAMPLE AND RESULTS OF EXPT 5

Results:

Commands: stcp ­p 7000 ­l 1024 1.0.1.6
                     rtcp ­p 7000 ­l 1024 

For first 6 nodes:
Initial error rate: 0.0

Initial data rate: 10 Mbps

Output Throughput: 654­1091

Input Throughput: 654­1091

Changed error rate: 1.0

Changed data rate: 10 Mbps

Output Throughput: 654­1091

Input Throughput: 654­1091

Error rate: 1.0 

 
Data rate: 100 Mbps

Output Throughput: 1547­9765

Input Throughput: 1547­9765

For 6­10 nodes:

Initial error rate: 0

Initial data rate: 10 Mbps

Output Throughput: 654­1091

Input Throughput: 654­1091

Changed error rate: 1.0

Data rate: 10 Mbps

Output Throughput: 654­1091

Input Throughput: 654­1091

 
EXPERIMENT 6

Simulate an Ethernet LAN using N nodes and set multiple traffic nodes 
and determine collisions across different nodes.

STEPS:

Step 1: Connect one set of hosts with a hub and another set of hosts also through a 
  hub and connect these two hubs through a switch. This forms an Ethernet 
  LAN.

 Step 2:  Setup multiple traffic connections between the hosts on one hub and 
    hosts on another hub using the following command:

stcp [­p port] [­l writesize] hostIPaddr
rtcp [­p port] [­l readsize] 

Step 3: Setup the collision log at the destination hosts in the MAC layer as 
described in the earlier experiments. 

Step 4: View the results in the filename.results.

 
The screenshot of the topology is shown below:

 
EXAMPLE AND RESULTS OF EXPT 6

Results:

Commands:  stcp ­p 7000 ­l 1024 1.0.1.6
                     rtcp ­p 7000 ­l 1024 

Drops at node 5 :   324­750
Drops at node 4 :   274­930

 
EXPERIMENT 7

Simulate an Ethernet LAN using N nodes and set multiple traffic nodes 
and plot congestion window for different source/destination.

STEPS:

Step 1: Connect one set of hosts with a hub and another set of hosts also through a 
  hub and connect these two hubs through a switch. This forms an Ethernet 
  LAN.

 Step 2:  Setup multiple traffic connections between the hosts on one hub and 
    hosts on another hub using the following command:

 
stcp [­p port] [­l writesize] hostIPaddr
rtcp [­p port] [­l readsize] 

Step 3: Setup the collision log at the destination hosts in the MAC layer as 
described in the earlier experiments. 

Step 4: To plot the congestion window go to Menu­>Tools­>Plot Graph­>File­
  >open­>filename.results­>filename.coll.log

Step 5: View the results in the filename.results.

The screenshot of the topology is shown below:

 
EXAMPLE AND RESULTS OF EXPT 7

Results:

Commands:  stcp ­p 7000 ­l 1024  1.0.1.6
                     rtcp ­p 7000 ­l 1024 

 
Drops at node 5 :   324­750

Drops at node 4 :   274­930

Note: The only difference between the 6th experiment and the present experiment 
is that here we need to plot the congestion window i.e. collision log.

EXPERIMENT 8

Simulate simple BSS and with transmitting nodes in wireless LAN by 
simulation and determine the performance with respect to transmission of 
packets.

 
STEPS:

Step 1: Connect a host and two WLAN access points to a router.

Step 2: Setup multiple mobile nodes around the two WLAN access points and set 
the path for each mobile node.

Step  3:  Setup  a   ttcp  connection  between   the  mobile  nodes   and  host using   the 
following command:

ttcp ­r ­u ­s [­p port number]

Step 4: Setup the input throughput log at the destination host.

Step 5: To set the transmission range go to Menu­>Settings­>WLAN mobile   
node­>Show transmission range.

Step 5:View the results in the filename. results.

The screenshot of the topology is shown below:

 
 
EXAMPLE AND RESULTS OF EXPT 8

Results:

Command: ttcp ­r ­u ­s ­p 7000
Output Throughput : 1190

 
PART­B

 
ERROR DETECTING CODE USING CRC­CCITT

Overview:
The accurate implementations (long­hand and programmed) of the 
16­bit CRC­CCITT specification, is as follows: 
● Width = 16 bits 
● Truncated polynomial = 0x1021 
● Initial value = 0xFFFF 
● Input data is NOT reflected 
● Output CRC is NOT reflected 
● No XOR is performed on the output CRC 

Theoretical Concepts:
      Important features of a standard CRC are that it: 
● Can be used to validate data 
● Is reproducible by others 

The first feature above is easy to realize in a closed system if corruption of data is 
infrequent (but substantial when it occurs). The term "closed system" refers to a 
situation where the CRC need not be communicated to others. A correct 
implementation of a 16­bit CRC will detect a change in a single bit in a message 
of over 8000 bytes. An erroneous CRC implementation may not be able to detect 
such subtle errors. If errors are usually both rare and large (affecting several bits), 
then a faulty 16­bit CRC implementation may still be adequate in a closed system. 
The second feature above ­­ that the CRC is reproducible by others ­­ is crucial in 
an open system; that is, when the CRC must be communicated to others. If the 
integrity of data passed between two applications is to be verified using a CRC 
defined by a particular standard, then the implementation of that standard must 
produce the same result in both applications ­­ otherwise, valid data will be 

 
reported as corrupt. 
Reproducibility may be satisfied by even a botched implementation of a standard 
CRC in most cases ­­ if everyone uses the same erroneous implementation of the 
standard. But this approach: 
● Modifies the standard in ways that are both unofficial and undocumented. 
● Creates confusion when communicating with others who have not adopted 
the botched implementation as the implied standard. 
The CRC value for the 9­byte reference string, "123456789" is 0xE5CC.
The need to focus on the 16­bit CRC­CCITT (polynomial 0x1021) and not CRC16 
(polynomial 0x8005),are as follows : 
● Is a straightforward 16­bit CRC implementation in that it doesn't involve: 
● reflection of data 
● reflection of the final CRC value 
● Starts with a non­zero initial value ­­ leading zero bits can't affect the 
CRC16 used by LHA, ARC, etc., because its initial value is zero. 
● It requires no additional XOR operation after everything else is done. The 
CRC32 implementation used by Ethernet, Pkzip, etc., requires this 
operation; less common 16­bit CRCs may require it as well. 
The need to use a 16­bit CRC instead of a 32­bit CRC is as follows : 
● Can be calculated faster than a 32­bit CRC. 
● Requires less space than a 32­bit CRC for storage, display or printing. 
● Is usually long enough if the data being safeguarded is fewer than several 
thousand bytes in length, e.g., individual records in a database. 

Example:­
Calculation of the 16­bit CRC­CCITT for a one­byte message consisting of the 
letter "A":
                    Quotient=           111100001110111101011001 
   poly=                                 ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 
          10001000000100001 ) 1111111111111111010000010000000000000000 
                                               10001000000100001 
                                               ­­­­­­­­­­­­­­­­­­­­­­­­­­­                                        red 
bits are initial value 
                                               11101111110111111                                          bold 

 
bits are message 
                                               10001000000100001                                          blue 
bits are augmentation 
                                                 ­­­­­­­­­­­­­­­­­­­­­­­­­­     
                                                11001111100111100 
                                               10001000000100001 
                                             ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­             
                                               10001111000111010 
                                               10001000000100001 
                                             ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 
                                                00001110000110110 
                                                00000000000000000 
                                              ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 
                                               00011100001101100 
                                               00000000000000000 
                                            ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 
                                               00111000011011000 
                                               00000000000000000 
                                            ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 
                                                01110000110110001 
                                                00000000000000000 
                                             ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 
                                               11100001101100010 
                                               10001000000100001 
                                             ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 
                                               11010011010000110 
                                               10001000000100001 
                                             ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ 
                                               10110110101001110 

 
EXPERIMENT 1

Write a program for error detecting code using CRC­CCITT (16­bits).

#include <stdio.h>
#include <string.h>

#define           poly     0x1021          /* crc­ccitt mask */

/* global variables */
char goodtext[1000];
char badtext[1000];
unsigned short good_crc;
unsigned short bad_crc;
unsigned short good_text_length;
unsigned short bad_text_length;

int main()
{
    void update_good_crc(unsigned short);

 
    void augment_message_for_good_crc();
    void augment_message_for_bad_crc();
    void update_bad_crc(unsigned short);

    unsigned short ch, i;

    good_crc = 0xffff;
    bad_crc = 0xffff;
    i = 0;
    good_text_length= 0;
    bad_text_length=0;

    printf("\n Enter Original Text:");
    scanf("%s",goodtext);
    printf("\n Enter Text to be verified:");
    scanf("%s",badtext);
    
    while((ch=goodtext[i])!=0)
    {
        update_good_crc(ch);
        i++;
        good_text_length++;
    }
    i=0;
    while((ch=badtext[i])!=0)
    {
        update_bad_crc(ch);
        i++;
        bad_text_length++;
    }

    
    augment_message_for_good_crc();
    augment_message_for_bad_crc();
    
    printf("\n CRC of Original Text    = %04X",good_crc);
    printf("\n CRC of  verified Text   = %04X",bad_crc);
    printf("\n Length of Original Text = %u",good_text_length);
    printf("\n Length of Verified Text      = %u",bad_text_length);

 
    if(good_crc!=bad_crc)
       printf("\n Data(CRC) mismatch!\n");
    else
       printf("\n Data(CRC) matched!\n");
    return(0);
}

void update_good_crc(unsigned short ch)
{
    unsigned short i, v, xor_flag;

    /*
    Align test bit with leftmost bit of the message byte.
    */
    v = 0x80;

    for (i=0; i<8; i++)
    {
        if (good_crc & 0x8000)
        {
            xor_flag= 1;
        }
        else
        {
            xor_flag= 0;
        }
        good_crc = good_crc << 1;

        if (ch & v)
        {
            /*
            Append next bit of message to end of CRC if it is not zero.
            The zero bit placed there by the shift above need not be
            changed if the next bit of the message is zero.
            */
            good_crc= good_crc + 1;
        }

 
        if (xor_flag)
        {
            good_crc = good_crc ^ poly;
        }

        /*
        Align test bit with next bit of the message byte.
        */
        v = v >> 1;
    }
}

void update_bad_crc(unsigned short ch)
{
    unsigned short i, v, xor_flag;

    /*
    Align test bit with leftmost bit of the message byte.
    */
    v = 0x80;

    for (i=0; i<8; i++)
    {
        if (bad_crc & 0x8000)
        {
            xor_flag= 1;
        }
        else
        {
            xor_flag= 0;
        }
        bad_crc = bad_crc << 1;

        if (ch & v)
        {
            /*
            Append next bit of message to end of CRC if it is not zero.
            The zero bit placed there by the shift above need not be

 
            changed if the next bit of the message is zero.
            */
            bad_crc= bad_crc + 1;
        }

        if (xor_flag)
        {
            bad_crc = bad_crc ^ poly;
        }

        /*
        Align test bit with next bit of the message byte.
        */
        v = v >> 1;
    }
}

void augment_message_for_good_crc()
{
    unsigned short i, xor_flag;

    for (i=0; i<16; i++)
    {
        if (good_crc & 0x8000)
        {
            xor_flag= 1;
        }
        else
        {
            xor_flag= 0;
        }
        good_crc = good_crc << 1;

        if (xor_flag)
        {
            good_crc = good_crc ^ poly;
        }
    }

 
}

void augment_message_for_bad_crc()
{
    unsigned short i, xor_flag;

    for (i=0; i<16; i++)
    {
        if (bad_crc & 0x8000)
        {
            xor_flag= 1;
        }
        else
        {
            xor_flag= 0;
        }
        bad_crc = bad_crc << 1;

        if (xor_flag)
        {
            bad_crc = bad_crc ^ poly;
        }
    }
}

FRAME SORTING TECHNIQUE USED IN BUFFERS

Overview & Theoretical Concepts:

 
We need the frame sorter when the frame source is using TCP/IP so 
we can run packet re­assemblers on other computers in an effort to balance the 
workload.

If the frames are coming in over ISIS IP multicasts, we don't need a sorter: Each 
re­assembler can receive all frames and discard those they don't need. This way 
we get each frame on the network one time only, and the work in each re­
assembler to input and reject frames on the wrong virtual channel is very little. If 
ISIS is not using true IP multicasting, then, once again, the sorter is needed to 
reduce the network traffic.

There are side benefits to such a design. In cases like I&T where the frame source 
is using TCP/IP, we need to sort the transfer frames by virtual channel so we can 
run some packet re­assemblers on other workstations to balance the compute load. 
But even so, we may re­assemble housekeeping packets on the workstation doing 
the frame sorting. Why do it in a separate process? This is especially true on 
Solaris where we have control over thread binding, and therefore, thread 
concurrency.

In a multi­threaded environment, the frame sorter and packet re­assembler both 
can be constructed from a collection of objects: input tasks, output tasks, packet 
assembly tasks, pool objects, sorter objects, and queue objects.

The packet re­assembler might looks like this:

input ­­> queue ­­> pkt assy ­­> sorter ­­> queue ­­> output

Transfer frames enter an input. Input enqueues and possibly archives them. The 
packet assembly task reads frames out of the queue and constructs packets. It 
hands completed packets to a sorter which enqueues them for output tasks and 
possibly archives them. Each output task reads packets from its queue and sends 
packets out.

EXPERIMENT 2

 
Write a program for frame sorting technique used in the buffers.

#include<stdio.h>

struct frame{
        int fslno;
        char finfo[20];
};

struct frame arr[10];
int n;

void sort()
{
        int i,j,ex;
        struct frame temp;
        for(i=0;i<n­1;i++)
        {
                ex = 0;
                for(j=0;j<n­i­1;j++)
                        if(arr[j].fslno > arr[j+1].fslno)
                        {
                                temp = arr[j];
                                arr[j] = arr[j+1];
                                arr[j+1] = temp;
                                ex++;
                        }
                if(ex==0) break;
        }
}

int main()
{
        int i;
        system("clear");
        printf("enter the number of frames\n");
        scanf("%d",&n);
        printf("enter the frame sequence number and frame contents\n");

 
        
        for(i=0; i<n; i++)
                scanf("%d%s",&arr[i].fslno,&arr[i].finfo);
        sort();
        printf("the frames in sequence\n");
        for(i=0;i<n;i++)
        {
                printf("01111110 %d\t%s 01111110\n",arr[i].fslno,arr[i].finfo);
                printf("|­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­|\n");
        }
}

 
DISTANCE VECTOR ALGORITHM 

Background:
 
One of the most popular & dynamic routing algorithms, the distance vector 
routing algorithms operate by using the concept of each router having to maintain 
a table( ie., a vector ), that lets the router know the best or shortest distance to each 
destination and the next hop to get to there. Also know as Bellman Ford(1957) and 
Ford Fulkerson (1962). It was the original ARPANET algorithm.

Algorithm Overview:

Each router maintains a table containing entries for and indexed by each 
other router in the subnet. 

Table contains two parts :

1.A preferred outing line.
2.Estimate of time or distance to that destination.

The metric used here is the transmission delay to each destination. This metric 
maybe number of hops, queue length, etc.

The router is assumed to know the distance metric to each of its neighbours.Across 

 
the network the delay is calculated by sending echo packets to each of neighbours.

Example

Dx(y) = min{c(x,y) + Dy(y), c(x,z) + Dz(y)}


= min{2+0 , 7+1} = 2

cost to cost to cost to


x y z x y z x y z
x 0 2 7 x 0 2 3 x 0 2 3
y ∞∞ ∞ y 2 0 1 y 2 0 1
z ∞∞ ∞ z 7 1 0 z 3 1 0
from from from
cost to cost to cost to
x y z x y z x y z y
2 1
x ∞ ∞
∞ x 0 2 7 x 0 2 3 x z
y 2 0 1 y 2 0 1 y 2 0 1 7
z ∞∞ ∞ z 7 1 0 z 3 1 0
from from from
cost to cost to cost to

x y z x y z x y z

x ∞∞ ∞ x 0 2 7 x 0 2 3

y ∞ ∞ ∞ y 2 0 1 y 2 0 1

  z 71 0 z 3 1 0 z 3 1 0
from from from
Execution Instructions

The program is typed on an editor (eg vi,gedit or kdevelop),exit the editor 
after saving the progarm,complile using the command cc <programname>.c and 
then the command ./a.out is entered if no errors are encountered(else correct the 
errors and then perform the above).

1: The program when executed asks the for the no of nodes.

2: Since we are using delay as the metric the program asks the user to input the 
first set of values for the delay from the individual nodes to all other nodes. Please 
enter the distance between the nodes to their neighbours else enter 999 if the nodes 
are not connected directly.

3: The program now will print out the initial configuration and the final 
configuration of the routing tables.

4: It will ask you whether you want to find out the shortest distance between any 2 
nodes.If yes enter the any number or alphabet else enter 0 to exit.

5: The program exits otherwise it will ask you to enter the pair of nodes between 
which the distance has to be found.It displays the shortest path as well as the route 
from the first node to the next node.  

 
EXPERIMENT 3

Write a program for distance vector algorithm to find suitable path for 
transmission.

#include <stdlib.h>
#define NUL 1000
#define NODES 10

struct node
{
        int t[NODES][3];
};

struct node n[NODES];
typedef struct node NOD;

int main()

 
{

        void init(int,int);
        void inp(int,int);
        void caller(int,int);
        void op(int,int,int);
        void find(int,int);

        int i,j,x,y,no;

        do{
                printf("\n Enter the no of nodes required(Less than 10 pls): ");
                scanf("%d",&no);
           }while(no>10||no<0);

        for(i=0;i<no;i++)
                {
                 init(no,i);
                 inp(no,i);
                }
 printf("\n The configuration of the nodes after initialization is as follows :");

        for(i=0;i<no;i++)
                op(no,i,0);

        for(j=0;j<no;j++)
                {
                 for(i=0;i<no;i++)
                        caller(no,i);
                }
        printf("\n The configuration of the nodes after computation of the paths is as 
follows :");

        for(i=0;i<no;i++)
                op(no,i,1);

        while(1)
        {
                printf("\n Enter 0 to exit or any other key to find the shortest path 

 
between two nodes!!");
                scanf("%d",&j);

                if(!j)
                        break;

                system("clear");

                do{
                        printf("\n enter the nodes between which the path is to be found : 
");
                        scanf("%d %d",&x,&y);
                }while((x<0 || x > no) && (y<0 || y > no));

                printf("\n The most suitable route from node %d to %d is as follows 
\n",x,y);

                find(x,y);

                printf(" %d",y);
 printf("\n The length of the shortest path between node %d and %d is %d 
",x,y,n[x­1].t[y­1][2]);

        }
        printf("\n This was the working of the Distance Vector Algorithm .. Arigato 
Sayonara\n");

void init(int no,int x)

{
        int i;

        for(i=0;i<no;i++)
                {
                 n[x].t[i][1]=i;

 
                 n[x].t[i][2]=999;
                 n[x].t[i][3]=NUL;
                }

        n[x].t[x][2]=0;
        n[x].t[x][3]=x;
}

void inp(int no,int x)

{
        int i;

        printf("\n Enter the distances from the node %d to the other nodes...",x+1);
        printf("\n Pls Enter 999 if there is no direct root from node ' %d ' to the node 
in question : ",x+1);

        for(i=0;i<no;i++)
                {
 if(i!=x)
                        {

                         do
                           {
                                printf("\n Enter Distance to node %d :",i+1);
                                scanf("%d",&n[x].t[i][2]);
                           } while(n[x].t[i][2]<0 || n[x].t[i][2]>999);

                         if(n[x].t[i][2]!=999)
                                n[x].t[i][3]=i;

                        }
                }

void caller(int no,int x)

 
{
        void compar(int,int,int);
        int i;

        for(i=0;i<no;i++)
                {
                 if(n[x].t[i][2]!=999 && n[x].t[i][2]!=0)
                        {
                         compar(x,i,no);
                        }
                }

void compar(int x,int y,int no)
{
        int i,z;

        for(i=0;i<no;i++)
                {
                 z = n[x].t[y][2]+n[y].t[i][2];

                 if(n[x].t[i][2] > z)
                        {
                         n[x].t[i][2]=z;
                         n[x].t[i][3]=y;
                        }
                }
}

void op(int no,int x,int z)

        int i,j;

 
        printf("\n The routing table for node no %d is as follows : ",x+1);
        printf("\n\n\t\t\tDESTINATION\tDISTANCE\tNEXT_HOP");

        for(i=0;i<no;i++)
                {
                 if((!z && n[x].t[i][2] >= 999) ||(n[x].t[i][2] >= (999*no)))
                        printf("\n\t\t\t     %d    \tNO LINK  \t NO HOP",n[x].t[i][1]+1);
                 else
                        if(n[x].t[i][3]==NUL)
                                printf("\n\t\t\t     %d    \t   %d    \t NO HOP",n[x].t[i]
[1]+1,n[x].t[i][2]);
                        else
                                printf("\n\t\t\t     %d    \t   %d    \t    %d",n[x].t[i][1]+1,n[x].t[i]
[2],n[x].t[i][3]+1);
                }
}

void find(int x,int y)

        int i,j;
        i = x­1;
        j = y­1;

        printf(" %d ­­­>",x);
        if(n[i].t[j][3]!=j)
                {
                        find(n[i].t[j][3]+1,y);
                        return;
                }

}
SPANNING TREE ALGORITHM 

    Overview:

 
Tree is a finite non­empty set of elements or nodes. One of the nodes is 
called the root. Each element in a tree is called a node of the tree. Remaining 
elements     
are partitioned into disjoint subsets.

Theoretical Concepts:
                    
Spanning Tree:
Spanning tree is a subset of the original topology that has no loops. It is a 
subgraph containing all the nodes of the graph and some arcs selected such that 
there is exactly one path between each pair of nodes.When weights are given for 
all pairs of nodes in a graph,the spanning tree with minimum total weight can be 
found leading to the minimum spanning tree.(Total weight equals sum of all its 
arcs).         
                         
Prim's Algorithm:

Here a node is chosen initially as the root. The nodes of the graph are then 
appended to the tree one at a time until all nodes are included in the tree. The node 
added to the tree at each point is the node adjacent  to a node of the tree by an arc 
of minimum weight. A minimum spanning tree is constructed when all the nodes 
of the graph are added to the tree.
The minimum spanning tree can be created from a weighted graph and this 
represents the cheapest way of connecting all nodes in the graph. To get the 
minimum spanning tree for the graph, a practical tree at any point is built by the 
prim's algorithm.

     

EXPERIMENT 3

 
Write a program for spanning tree algorithm (Kruskal's/Prim's) to 
find loop less path. 

Prims:

#include<stdio.h>
#include<stdlib.h>

#define MAX 20
#define INFINITY 999

enum boolean{FALSE,TRUE};
void prim(int c[][MAX],int t[MAX],int n);
int mincost=0;

int main()
{
  int n,c[MAX][MAX],t[2*(MAX­1)];
  int i,j;

  printf("this program implements prims algorithm");
  printf("\nhow many nodes does the graph have");
  scanf("%d",&n);
  printf("enter the cost adjacency matrix");
  printf("999 indicates no connection;\n");
  for(i=0;i<n;i++)
   for(j=0;j<n;j++)
     scanf("%d",&c[i][j]);
  prim(c,t,n);
  printf("spanning tree:\n");
   for(i=0;i<2*(n­1);i+=2)
       printf("(%d,%d)\n",t[i]+1,t[i+1]+1);
       printf("mincost= %d",mincost);

       return 0;
}
void prim(int c[][MAX],int t[MAX],int n)

 
{
  int i,j;
  enum boolean v[MAX];
int k,s,min,v1,v2;
  for(i=0;i<n;i++)
    v[i]=FALSE;
  v[0]=TRUE;
  k=0;
  t[k]=1;
  s=0;
  k++;
  while(k<n)
  {
      min=INFINITY;
      for(i=0;i<n;i++)
      for(j=1;j<n;j++)
        if(v[i]==TRUE&&v[j]==FALSE&&c[i][j]<min)
        {
          min=c[i][j];
          v1=i;
          v2=j;
       }
       mincost=mincost+min;
       if(min==INFINITY)
       {
         printf("graph disconnected:spanning tree impossible.\n");
         exit(1);
       }
       v[v2]=TRUE;
       k++;
       t[s++]=v1;
       t[s++]=v2;
     }
}

 
CLIENT SERVER PROGRAM USING SOCKET 
PROGRAMMING

i. OVERVIEW

Unix sockets is just like two way FIFO's. All data communication will take 
place through the socket's interface, instead of through the file interface. Although 
unix socket's are a special file in the file system(just like FIFO's), there's usage of 
socket(), bind(), recv(),etc and not open(), read().

When programming with socket's, usually there's creation of  server and 
client programs. The server will sit listening for incoming connections from clients 
and handling. This is similar to the situation that exists with internet sockets but 
with fine differences.

For instance, when describing which unix socket that has to be used(i.e the 
path to the special file that is the socket). The structure “struct sockaddr_un” has 
the following fields:

struct sockaddr_un{
         unsigned short   sa_family;         // Address family,AF_XXXX
                                  char                    sa_data;            // 14 bytes of protocol 
address
                         };

This is the structure you will be passing to the bind() function, which 
associates a socket descriptor(a file descriptor) with a certain file(the name for 
which is in the sun_path field).

 
The structure “struct sockaddr_in” is used when we need IP address and Port 
number to be binded to the Sockets. It has following fields:
struct sockaddr_in {
                                 short int                  sin_family;    // Address family
                            unsigned short int  sin_port;        // Port number
         struct in_addr         sin_addr;       // Internet address
         unsigned char        sin_zero[8]    // Same size as struct sockaddr 
};
                       // Internet adress
                        struct in_addr {
           unsigned long s_addr;                  // 32 bits or 4 bytes long  
};
ii. BACKGROUND REQUIRED:

1. UNIX File I/O system calls
2. UNIX IPC system calls
3. UNIX socket programming 

iii. THEORETICAL CONCEPTS:

   Most interprocess communication uses the client server model. These terms 
refer to the two processes which will be communication with each other. One of 
the two processes , the client , connects to the other process, the server, typiceally 
to make a request for information. A good analogy is a person who makes a phone 
call to another person.
Notice that the client needs to know of the existence of and the address of 
the server, but the server does not need to know the adresss of(or even the 
existence of) the client prior to the connection being established. Notice also that 
once a connection is established, both sides can send and receive information.
The system calls for establishing a connection are somewhat different for 
the client and the  server, but both involve the basic construct of a socket. A socket 
is one end of an interprocess communication channel. The two processes each 
establish their own socket.
The steps involved in establishing a socket on the client side are as follows­
1. Create a socket with the socket() system call .
2. Connect the socket to the address of the server using the connect() system 
call.

 
3. Send and receive data.There are a number of ways to do this, but the 
simplest is to use the read() and write() systen calls.
         The stepd involved in establishing a socket on the server side are as 
follows­        
1. Create a socket with the socket() system call.
2. Bind the socket to an address using the bind() system call. For a server 
socket on the internet,an address consists of a port number on the host 
machine.
3. Listen for connections with the listen() system call.
4. Acept a connection with the accept() system call. This call typically 
blocks until a client connects with the server.
5. Send and receive the data.

Socket Types:

  When a socket is created, the program has to specify the address domain 
and the socket type. Two processes can communicate with each other only if their 
sockets are of the same type and in the same domain, in which two processes 
running on any two hosts on the Internet communicate. Each of these has it's own 
adress format.
The address of a socket in the Unix domain is a character string which is 
basically an entry in the file system.
                         The address of a socket in the Internet domain consists of the 
Internet address of the host machine (every computer on the Internet has a unique 
32 bit address, often reffered to as it's IP address). In addition , each socket needs a 
port number on that host. Port numbers are 16 bit unsigned integers. The lower 
numbers are reserved in Unix for standard services. For eg, the port number for the 
FTP server is 21.
There are two widely used socket types, stream sockets , and datgram 
sockets. Stream sockets treat communications as a continuous stream of 
characters, while datagram sockets have to read entire messages at once. Each uses 
it's own communications protocol. Stream sockets use TCP , which is a reliable , 
stream oriented protocol, and datagram sockets use UDP, which is unreliable and 
message oriented.

The primary socket calls are as follows:­
1. socket()  ­ Create a new socket and return it's descriptor.

 
2. bind()  ­ Associate a socket with a port and address .
3. Listen() ­Establish a queue for connection requests.
4. Accept()­ Accepts a connection request.
5. Connect()­ Initiate a connection to a remote host.
6. Recv() ­ Receive data from a socket descriptor.
7. Send() ­ Send data to a socket descriptor.
8. Close() ­ “one­way” close of a socket descriptor,

The other system calls used are as follows:­
1. gethostbyname­ given a hostname , returns a structure which specifies it's 
DNS name(s) and IP address(es).
2. getservbyname – given service name and protocol , returns a structure which 
specifies its name(s) and its port address.
The socket utility functions are as follows:­

1. htons/ntohl­ convert short/long from host byte order  to network byte order.
2. inet_ntoa/inet_addr­ converts 32 bit IP address (network byte order to/from a 
dotted decimal string)

The header files used in order are:­
1.<sys/types.h> ­prerequisite typedefs.
2. <errno.h> ­names for “erno” values (error numbers)
3. <sys/socket.> ­ struct sock addr ;system prototypes  and constants .
4. <netdb.h.h> ­ network info lookup prototypes and structures.
5. <netinet/in.h> ­ struct sockaddr_in; byte ordering macros.
6. <arpa/inet.h> ­ utility function prototypes.

 iv. EXECUTION INSTRUCTIONS:

There are two programs(Server­side & Client­side) to be typed on an 
editor (eg vi or kdevelop), exit the editor after saving the progarm, complile the 
programs on different terminals using the command “cc  <programname>.c  ­o 
<output filename>” and then the command “./<output filename>” is entered if no 
errors are encountered(else correct the errors and then perform the above).

1. Compile and execute the Server side program specifying an unsed port no. 
after the ouput filename, then in the other terminal compile and execute the 
Client side program with IP address of Server system and common port no.
2. Enter  the pathname of any file on the Server system as a request to the Server 

 
and wait for reply.
3. Now switch to Server terminal and check if the file requested is present or not 
and the status of Server. If the file is found then  switch to the Client terminal 
and watch the contents of file displayed on the terminal. Else it displays that file 
is not found with pathname. 

EXPERIMENT 5

Using TCP/IP sockets, write a client­server program to make client 
sending the file name and the server to send back the contents of the 
requested file if present.

server program:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

void error(char *msg)
{
    perror(msg);
    exit(1);
}

 
int main(int argc, char *argv[])
{
        int sockfd, newsockfd, portno, clilen,n;
        char buffer[256],c[2000];
        struct sockaddr_in serv_addr, cli_addr;
        FILE *fd;

        if (argc < 2)
        {
                fprintf(stderr,"ERROR, no port provided\n");
                exit(1);
        }
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
                error("ERROR opening socket");
        bzero((char *) &serv_addr, sizeof(serv_addr));

        portno = atoi(argv[1]);
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        serv_addr.sin_port = htons(portno);

        if (bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
                error("ERROR on binding");
listen(sockfd,5);

        clilen = sizeof(cli_addr);
        printf("SERVER: Waiting for client...\n");
        newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);
        if (newsockfd < 0)
                error("ERROR on accept");

        bzero(buffer,256);
        n = read(newsockfd,buffer,255);
        if (n < 0)
                error("ERROR reading from socket");
        printf("SERVER: %s \n",buffer);
        if((fd=freopen(buffer,"r",stdin))!=NULL)

 
        {
                printf("SERVER: %s found!\nTransfering the contents...\n",buffer);
                if(fgets(c,2000,stdin)!=NULL);
                        n = write(newsockfd,c,1999);
                if (n < 0)
                        error("ERROR writing to socket");
        }
        else
        {
                printf("SERVER: File not found!\n");
                n=write(newsockfd,"File not found!",15);
                if (n < 0)
                        error("ERROR writing to socket");
        }

        return 0;
}

client program:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>

void error(char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{
        int sockfd, portno, n;
        struct sockaddr_in serv_addr;
        struct hostent *server;
        char buffer[256],buf[2000];

 
        if (argc < 3)
        {
                fprintf(stderr,"usage %s hostname port\n", argv[0]);
                exit(0);
        }

        portno = atoi(argv[2]);
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
                error("ERROR opening socket");
        printf("\nClient Online!\n");

        server = gethostbyname(argv[1]);
        if (server == NULL)
        {
             fprintf(stderr,"ERROR, no such host\n");
                exit(0);
        }
        printf("\nSERVER Online!\n");

        bzero((struct sockaddr_in *)&serv_addr,sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        bcopy((char *)server­>h_addr,(char *)&serv_addr.sin_addr.s_addr,server­
>h_length);
        serv_addr.sin_port = htons(portno);

        if (connect(sockfd,&serv_addr,sizeof(serv_addr)) < 0)
                error("ERROR connecting");

        printf("CLIENT: Enter path with filename:\n");
        scanf("%s",&buffer);

        n = write(sockfd,buffer,strlen(buffer));
        if (n < 0)
                error("ERROR writing to socket");

        bzero(buf,2000);

 
        n = read(sockfd,buf,1999);
        if (n < 0)
                error("ERROR reading from socket");
        printf("CLIENT: Displaying contents of %s \n",buffer);
        fputs(buf,stdout);

        return 0;
}

MESSAGE QUEUES / FIFOs AS IPC CHANNELS

 
Client – Server communication using FIFO as IPC

i. OVERVIEW:

FIFO's  is used to send data between a Client and Server. If we have a 
server that is contacted by numerous clients, each client can write its request to a 
well­known(i.e, the pathname is known by all clients) FIFO that the server creates. 
The figure below shows this arrangement. Since there are multiple writers for the 
FIFO, the requests sent by the clients to the server need to be less than PIPE_BUF 
bytes in size. This prevents any interleaving of the client writes.

The problem in using FIFO's for this type of client­server communication is 
how to send replies back from the server to each client. A single FIFO can't be 
used, as the clients would never know when to read their response, versus 
responses for other clients. One solution is for each client to send its process ID 
with the request. The server then creates a unique FIFO for each client, using a 
pathname based on the client's process ID.

Server

Client­specific Well­known Client­specific


FIFO FIFO FIFO

Client Client

 
ii. BACKGROUND REQUIRED:

1. UNIX File I/O system calls
2. UNIX IPC system calls

iii. ALGORITHM:  There are two programs­ Server side & Client side.

Server side:
1. Create a well­known FIFO using “mknod” command.
Ex: mknod(<fifo name>, S_IFIFO | 0666 , 0)
2. Open the above FIFO in readonly mode to accept requests from the 
clients.
3. When the client opens the other end of FIFO in writeonly mode then 
read the contents and store the request(pathname of file) in a buffer.
4. Now create another FIFO(client­specific) in writeonly mode to send 
the reply(contents of the file requested) 
5. Open the file requested by client and write the contents into the 
client­speicfic FIFO and terminate the connection. 

Client side:
1. Open the well­known Server FIFO in write mode.
2. Write the pathname of file into this FIFO and send as a request.
3. Now open the Client­specific FIFO in read mode and wait for reply 
from server.
4. When the contents of file are available on this FIFO display it on the 
terminal.

iv. EXECUTION INSTRUCTIONS:

There are two programs(Server­side & Client­side) to be typed on an 
editor (eg vi or kdevelop), exit the editor after saving the progarm, complile the 
programs on different terminals using the command “cc  <programname>.c” and 
then the command “./a.out” is entered if no errors are encountered(else correct the 
errors and then perform the above).

 
1. Compile and execute the Server side progarm first then in the other terminal 
compile and execute the client side program.
2. Enter  the pathname of any file on the system as a request to the Server and wait 
for reply.
3. Now switch to Server terminal and check if the file requested is present or not 
and the status of Server. If the file is found then  switch to the Client terminal 
and watch the contents of file displayed on the terminal. Else it displays that file 
is not found with pathname. 

 
EXPERIMENT 6

Implement the above program using as message queues of 
FIFOs as IPC channel.

server program:

 #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>

    #define FIFO1_NAME "fifo1"
    #define FIFO2_NAME "fifo2"

int    main()
    {
        char p[100],f[100],c[300];
        int num,num2,fl,fd,fd2;

        mknod(FIFO1_NAME, S_IFIFO | 0666, 0);
        mknod(FIFO2_NAME, S_IFIFO | 0666, 0);

        printf("SERVER Online!\n\n");

 
        fd = open(FIFO1_NAME, O_RDONLY);
        printf("Client Online!\n Waiting for request...\n\n");

        while(1)
         {
            if ((num = read(fd, p, 100)) == ­1)
                perror("read error\n");
            else {
                  p[num] = '\0';
                  if((fl=open(p,O_RDONLY))<0)
                   {
                    printf("\nSERVER: %s not found!\n",p);
                    exit(1);
                   }
   else
                   {
                    printf("SERVER: %s found!\nTransfering the contents...\n ",p);
                    stdin=fdopen(fl,"r");
                    if(fgets(c,300,stdin)!=NULL)
                    {
                     fd2=open(FIFO2_NAME, O_WRONLY);
                     if(num2=write(fd2,c,strlen(c))==­1)
                        perror("Tranfer error\n");
                     else
                        printf("SERVER: Transfer Completed!\n");                        }
                    else  perror("read error\n");
                    exit(1);
                   }
                 }
        }
    }

client program:

   #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>

 
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>

    #define FIFO1_NAME "fifo1"
    #define FIFO2_NAME "fifo2"

int main()
    {
        char p[100],f[100],c[300];
        int num,num2,fl,fd,fd2;

        mknod(FIFO1_NAME, S_IFIFO | 0666, 0);
        mknod(FIFO2_NAME, S_IFIFO | 0666, 0);

        printf("\nWaiting for SERVER...\n");
        fd = open(FIFO1_NAME, O_WRONLY);
        printf("\nSERVER Online!\nClient: Enter the path\n");

        while (gets(p), !feof(stdin)) {
            if ((num = write(fd, p, strlen(p))) == ­1)
                perror("write error\n");
            else
               {
                printf("Waiting for reply...\n");
                fd2 =open(FIFO2_NAME , O_RDONLY);
                if((num2=read(fd2,c,300))==­1)
                  perror("Transfer error!\n");
                else
                  {
                   printf("File recieved! Displaying the contents:\n\n");
   (fputs(c,stdout)==EOF)
                        perror("print error\n");
                   exit(1);
                  }
                }
            }
    }

 
RSA ALGORITHM

Overview:

The RSA Public key algorithm was invented in 1977 by Ron Rivest, Adi Shamir 
and Leonard Adleman (RSA). 
The algorithm Supports Encryption and Digital Signatures. It is the most widely 
used public key algorithm. 
RSA gets its security from the integer factorization problem. The algorithm is 
relatively easy to 
understand and implement. It has been patent free since 2000.

RSA is used in security protocols such as IPSEC/IKE ­IP data security,TLS/SSL 
­transport data security (web),
PGP ­email security,SSH ­terminal connection security,SILC ­conferencing 
service security.

 
Theoretical Concepts:

RSA gets its security from the factorization problem. The difficulty of factoring 
large numbers is 
the basis of security of RSA.

The Integer factorization problem (finding a number's prime factors):

For a positive integer n, find its prime factors: 
n = p1 p2 ... pi where pi is positive distinct prime number

Example: 257603 = 41 * 61 * 103

Factorization algorithms can be used to factor faster than brute forcing. Some of 
them are Trial division, 
Pollard's rho, Pollard's p­1, Quadratic sieve, elliptic curve factorization, Random 
square factoring, 
Number field sieve, etc.

A Prime number is a positive integer and is divisible only by itself and 1. Prime 
numbers are found 
with primality testing; an algorithm which tests a probable prime for primality. If 
primality testing 
returns false prime numbers the cryptographic algorithm may be insecure (or will 
not function correctly).

RSA depends on prime numbers in key generation. It also uses �strong� primes, 
numbers whose factors of 
the prime are also primes.

The RSA algorithm:

Key generation:

1)Select random prime numbers p and q, and check that p != q

2)Compute modulus n = pq

 
3)Compute phi = (p ­ 1)(q ­ 1)

4)Select public exponent e, 1 < e < phi such that gcd(e,phi) = 1

5)Compute private exponent d = e^­1 mod phi

6)Public key is {n, e}, private key is d

Encryption: c = me mod n, decryption: m = cd mod n

The selected public exponent e, which is used as public key with n. It is used to 
encrypt messages and to 
verify digital signatures. The e is stored for later with n. The e is usually small 
number but it 
can be 1 < e < phi . The e must be relatively prime to phi , hence gcd(e, phi ) = 1.
(gcd = greatest common divisor, using the  Euclidean algorithm)

The private exponent d, is the actual RSA private key. The d must not be disclosed 
at any time 
or the security of the RSA is compromised. The d is found by computing the 
multiplicative 
inverse d = e^­1 mod phi . The extended Euclidean algorithm is commonly used to 
compute inverses. 
The d exponent is used to decrypt messages and to compute digital signatures. 
Implementations try to 
find as small d as possible to make decryption faster. This is fine as long as it is 
assured that d 
is about the same size as n. If it is only one quarter of size it is not considered safe 
to be used. 
It is possible to find a smaller d by using lcm(p­1,q­1) instead of phi (lcm = least 
common multiple, 
lcm(p­1,q­1) = phi /gcd(p­1,q­1) ).

Example of RSA with small numbers:

p = 47, q = 71, compute n = pq = 3337

 
Compute phi = 46 * 70 = 3220

Let e be 79, compute d = 79­1 mod 3220 = 1019

Public key is n and e, private key d, discard p and q.

Encrypt message m = 688, 68879 mod 3337 = 1570 = c.

Decrypt message c = 1570, 15701019 mod 3337 = 688 = m.

Execution Instructions:

The program is typed on an editor (eg vi,gedit or kdevelop),exit the editor 
after saving the progarm, complile using the command cc <programname>.c and 
then the command ./a.out is entered if no errors are encountered(else correct the 
errors and then perform the above).

1: The program when executed will ask for two prime numbers to be entered for p 
and q respectively.
2: Then the value of e has to entered. It is preferred if p is greater than q and e is 3 
for testing.
3: The message to be encrypted has to be entered.
4: The program will display the original message, encrypted message and the 
decrypted message.

EXPERIMENT 7

Write a program for simple RSA algorithm to encrypt and decrypt the 
data.

#include<stdio.h>
#include<math.h>

double min(double x, double y)

 
{
 return(x<y?x:y);
}

double max(double x,double y)
{
 return(x>y?x:y);
}

double gcd(double x,double y)
{
        if(x==y)
                return(x);
        else
                return(gcd(min(x,y),max(x,y)­min(x,y)));
}

long double dbin(long double n)
{
 long double i=0,s=0,v,b,m=0;
      do{
        s+=pow(10,i)*(fmod((int)n,2));
        i++;
        n=n/2;
        }
 while(n>=1);

        return(s);
}

int  integral(long double num)
{
        long double integr=0;
        int frac;
        frac=(int)fmodl(num,10);
        return(frac);
}
long double modexp(long double a,long double x,long double n)

 
{
        long double r=1;

        while(x>0)
        {
                if ((int)(fmodl(x,2))==1)
                {
                        r=fmodl((r*a),n);
                }

                a=fmodl((a*a),n);
                x/=2;
        }
        return(r);
}

int main()
{
 long double p,q,phi,n,e,d,cp,cq,dp,dq,mp,mq,sp,sq,rp,rq,qInv,h;
 long double ms,es,ds;

        do{
                printf("\n Enter prime numbers p and q:");
                scanf(" %Lf %Lf",&p,&q);
          }
        while(p==q);

        n=p*q;
        phi=(p­1)*(q­1);

        do{
                printf("\n Enter prime value of e:");
                scanf(" %Lf",&e);
          }
                                                                                                           
 while((gcd(e,phi)!=1)&&e>phi); /*for e being relatively prime to phi */

 
        for(d=1;d<phi;++d)
        {
                if(fmod((e*d),phi)==1)
                        break;
        }

        printf("\n D within main = %Lf",d);

        /* public key is {n,e} private key is d */

        printf("\n Enter the message:");
        scanf(" %Lf",&ms);

        es=modexp(ms,e,n);
        ds=modexp(es,d,n);

        printf("\n Original Message  : %Lf",ms);
        printf("\n Encrypted Message : %Lf",es);
        printf("\n Decrypted Message : %Lf\n",ds);

 return(0);
}

 
HAMMING CODES

Overview:

Developed by 1947 Richard. W. Hamming for detecting and correcting single bit 
errors in transmitted data. This technique requires that three parity bits (or check 
bits) be transmitted with every four data bits. The algorithm is called a (7, 4) code, 
because it requires seven bits to encoded four bits of data.

Theoretical Concepts :

Background Concepts Required:
1. matrix multiplication
2. modulo 2 arithmetic
3. parity.

Parity:
A parity bit is an extra bit that forces a binary string to have a specific 
parity.

Two types:
1. Even(Even number of 1's ie.,the modulo 2 sum of the bits is 0)
2. Odd (Odd number  of 1's ie.,the modulo 2 sum of the bits is 1)

The table below lists all possible three bit values and value of a parity bit 
required to create a four bit sequence with even parity.

3 Bit String Parity Bit Verification

      000      0 0 + 0 + 0 + 0     =      0


      001        1 0 + 0 + 1 + 1     =      0
      010      1 0 + 1 + 0 + 1     =      0
      011      0 0 + 1 + 1 + 0     =      0

 
      100        1 1 + 0 + 0 + 1     =      0
      101      0 1 + 0 + 1 + 0     =      0
      110      0 1 + 0 + 1 + 0     =      0
      111        1 1 + 1 + 1 + 1     =      0

Table 1. Even Parity

It is very common for communication protocols to specify that a block of 
bits will be transmitted with a specific parity. If a block of data arrives at its 
intended destination with a parity other than the specified parity, it must be the 
case that at least one of the bits has been corrupted. A single parity bit is not 
sufficient to identify an even number of bits with errors, nor is it sufficient to 
allow the receiver to correct an error. Hamming codes use multiple parity bits to 
allow for error correction.

Encoding

Traditional Hamming codes are (7, 4) codes, encoding four bits of data into 
seven bit blocks (a Hamming code word). The extra three bits are parity bits. Each 
of the three parity bits are parity for three of the four data bits, and no two parity 
bits are for the same three data bits. All of the parity bits are even parity.

Example:

Given: data bits d1, d2, d3, and d4

A (7, 4) Hamming code may define parity bits p1, p2, and p3 as
p1 = d2 + d3 + d4
p2 = d1 + d3 + d4
p3 = d1 + d2 + d4 

There's a fourth equation for a parity bit that may be used in Hamming 
codes:
p4 = d1 + d2 + d3 

Valid Hamming codes may use any three of the above four parity bit 
definitions. Valid Hamming codes may also place the parity bits in any location 

 
within the block of 7 data and parity bits. Two Hamming codes with different 
parity bits or parity bits in a different bit position are considered equivalent. They 
will produce different results, but they are still Hamming codes.

One method for transforming four bits of data into a seven bit Hamming 
code word is to use a 4×7 generator matrix [G].

Define d to be the 1×4 vector [d1 d2 d3 d4]

It's possible to create a 4×7 generator matrix [G] such that the product 
modulo 2 of d and [G] (d[G]) is the desired 1×7 Hamming code word. Here's how 
it's done:

Step 1.
Represent each data bit with a column vector as follows:

         | 1 |
d1 =  | 0 |
         | 0 |
         | 0 |

         
         | 0 |
d2 =  | 1 |
         | 0 |
         | 0 |

         | 0 |
d3 =  | 0 |
         | 1 |
         | 0 |

         | 0 |
d4 =  | 0 |
         | 0 |
         | 1 |

Step 2.

 
Represent each parity bit with a column vector containing a 1 in the row 
corresponding to each data bit included in the computation and a zero in all other 
rows. Using the parity bit definitions from the example above:

         | 0 |
p1 =  | 1 |
         | 1 |
         | 1 |

         | 1 |
p2 =  | 0 |
         | 1 |
         | 1 |

         | 1 |
p3 =  | 1 |
         | 0 |
         | 1 |

Step 3:
Arrange the column vectors from the previous steps into a 4×7 matrix such 
that the columns are ordered to match their corresponding bits in a code word.

Using the vectors from the previous steps, the following will produce code 
words of the form     [p1 p2 p3 d1 d2 d3 d4] 

         | 0 1 1 1 0 0 0 |
 G =  | 1 0 1 0 1 0 0 |
         | 1 1 0 0 0 1 0 |
         | 1 1 1 0 0 0 1 |

Arranging the columns in any other order will just change the positions of bits in 
the code word. 

Example:

Encode the data value 1010 using the Hamming code defined by the matrix G 

 
(above).

                                  | (1 × 0) + (0 × 1) + (1 × 1) + (0 × 1) |     | 1 |


                                  | (1 × 1) + (0 × 0) + (1 × 1) + (0 × 1) |     | 0 |
                  | 0 1 1 1 0 0 0  |    | (1 × 1) + (0 × 1) + (1 × 0) + (0 × 1) |     | 1 |
|1010 |       | 1 0 1 0 1 0 0  |      =  | (1 × 1) + (0 × 0) + (1 × 0) + (0 × 0) |  = | 1 |
                  | 1 1 0 0 0 1 0  |    | (1 × 0) + (0 × 1) + (1 × 0) + (0 × 0) |     | 0 |
                  | 1 1 1 0 0 0 1  |    | (1 × 0) + (0 × 0) + (1 × 1) + (0 × 0) |     | 1 |
                                  | (1 × 0) + (0 × 0) + (1 × 0) + (0 × 1) |     | 0 |

So 1010 encodes to 1011010. Equivalent Hamming codes represented by 
different generator matrices will produce different results.

Decoding

In a world without errors decoding a Hamming code word would be very 
easy. Just throw out the parity bits. The encoding example produced a 7 bit code 
word. Its parity bits are 101 and its data bits are 1010. If you receive a 1011010, 
just decode it as 1010. But what happens if you receive a code word with an error 
and one or more of the parity bits are wrong.

Suppose the Hamming code defined by the matrix G in the example above 
is being used and the code word 1011011 is received. How is that word decoded? 
The first step is to check the parity bits to determine if there is an error.

Arithmetically, parity may be checked as follows:

p1 = d2 + d3 + d4 = 0 + 1 + 1 = 0
p2 = d1 + d3 + d4 = 1 + 1 + 1 = 1
p3 = d1 + d2 + d4 = 1 + 0 + 1 = 0 

In this case every parity bit is wrong. p1, p2, and p3 should have been 010, 
but we received 101.

Parity may also be validated using matrix operations. A 3×7 parity check 
matrix [H] may be constructed such that row 1 contains 1s in the position of the 
first parity bit and all of the data bits that are included in its parity calculation. 

 
Row 2 contains 1s in the position of the second parity bit and all of the data bits 
that are included in its parity calculation. Row 3 contains 1s in the position of the 
third parity bit and all of the data bits that are included in its parity calculation.

Example:

Using the code from example above, the matrix H may be defined as 
follows:

         | 1 0 0 0 1 1 1 |
    H =  | 0 1 0 1 0 1 1 |
         | 0 0 1 1 1 0 1 |

Multiplying the 3×7 matrix [H] by a 7×1 matrix representing the encoded 
data produces a 3×1 matrix called the "syndrome". There are two useful 
proprieties of the syndrome. If the syndrome is all zeros, the encoded data is error 
free. If the syndrome has a non­zero value, flipping the encoded bit that is in the 
position of the column matching the syndrome will result in a valid code word.

Example:

Using the parity check matrix from the example above we can correct and verify 
the code word 1011011.

                      | 1 |
| 0 | 
 | 1000111 |   | 1 |     |(1×1)+(0×0)+(0×1)+(0×1)+(1×0)+(1×1) +(1×1) |         | 1 |
 | 0101011 |   | 1 |  = |(0×0)+(1×0)+(0×1)+(1×1)+(0×0)+(1×1)+(1×1) |    =   | 1 |
 | 0011101 |   | 0 |     |(0×1)+(0×0)+(1×1)+(1×1)+(1×0)+(0×1)+(1×1) |          | 1 |
                     | 1 |
                     | 1 |

A column of all 1s is not the column of all 0s, so there is a parity error. 
Looking back at the matrix [H], you will see that the seventh column is all 1s, so 

 
the seventh bit is the bit that has an error. Changing the seventh bit produces the 
code word 1011010.

                   | 1 |
                   | 0 |
 |1000111|            | 1 |       |(1×1)+(0×0)+(0×1)+(0×1)+(1×0)+(1×1)+(1×0) |       | 0 |
 |0101011|            | 1 |  =   |(0×0)+(1×0)+(0×1)+(1×1)+(0×0)+(1×1)+(1×0) |  =  | 0 |
 |0011101|            | 0 |       |(0×1)+(0×0)+(1×1)+(1×1)+(1×0)+(0×1)+(1×0) |       | 0 |
                             | 1 |
                             | 0 |

Sure enough 1011010 is a valid code word. As I stated at the top of this 
section remove the parity bits to get the encoded value. In this case 1011011 was 
likely transmitted as 1011010, which encodes 1010.

Execution Instructions:

There are two parts to the program:

1:  Encoding.
2: Decoding.

The program is typed on an editor (eg vi,gedit or kdevelop),exit the editor 
after saving the program, compile using the command cc <program name>.c and 
then the command ./a.out is entered if no errors are encountered(else correct the 
errors and then perform the above).

Encoding: 

1: The program when executed asks the user for the 4 data bits (Please enter 
only binary digits).
2:  The program then proceeds to output the Data and Parity Matrix as well as 
the Generator Matrix for the given data bits.

 
3:  The program then outputs the encoded data bits in (7,4) format.

Decoding:

1: The program when executed asks for the encoded data bits to be entered 
(Please enter only binary digits).
2: The program (for that matter hamming codes) can only detect 1 bit errors in 
the data bits. if an error is made in the parity bits the user is returned a number 
based on the new parity bits. If there is just a single bit error the program prints the 
bit in which the error has occurred and then proceeds to print the corrected data 
bits else if there is no error then it gives a message of “Error Free Data” prints the 
data bits by truncating the first 3 bits of the encoded data entered.

EXPERIMENT 8

Write a program for Hamming Code generation  for error detection 
and correction.

program for encoding:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

char d1[5],d2[5],d3[5],d4[5];
char gmatrix[4][8];
char p1[5],p2[5],p3[5];

 
char data[5];
int encoded[8];         /*encoded matrix*/

int con(char x);

int main()
{
        int i,j;

        system("clear");
        printf("\nProgram for Hamming Code Implemetation ­Encoding\n");
        printf("Enter 4 data bits\n");

        scanf("%s",data);
//      printf("%s\n",data);

        /*set data n parity bits*/

        for(i=0;i<4;i++)
        {
                d1[i]=d2[i]=d3[i]=d4[i]='0';
                p1[i]=p2[i]=p3[i]='1';
        }

        printf("­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­\n");
        d1[0]='1';
        d2[1]='1';
        d3[2]='1';
        d4[3]='1';
 p1[0]='0';
        p2[1]='0';
        p3[2]='0';

        printf("%s\n",d1);
        printf("%s\n",d2);
        printf("%s\n",d3);
        printf("%s\n",d4);
        printf("%s\n",p1);
        printf("%s\n",p2);

 
        printf("%s\n",p3);

        for(i=0;i<4;i++)
                gmatrix[i][0]=p1[i];

        for(i=0;i<4;i++)
                gmatrix[i][1]=p2[i];

        for(i=0;i<4;i++)
                gmatrix[i][2]=p3[i];

        for(i=0;i<4;i++)
                gmatrix[i][3]=d1[i];

        for(i=0;i<4;i++)
                gmatrix[i][4]=d2[i];

        for(i=0;i<4;i++)
                gmatrix[i][5]=d3[i];

        for(i=0;i<4;i++)
                gmatrix[i][6]=d4[i];

        printf("\ngenerator matrix\n");
        for(i=0;i<4;i++)
                printf("%s\n",gmatrix[i]);
 /***** Ecoding******/

        for(i=0;i<7;i++)
                for(j=0;j<4;j++)
                        encoded[i]=encoded[i]+con(data[j])*con(gmatrix[j][i]);
        puts("encoded");
        for(i=0;i<7;i++)
        {
                encoded[i]=encoded[i]%2;
                printf("%i",encoded[i]);
        }
        puts("");
/

 
******************************************************************
****************/
        return 0;
}

int con(char x)
{
        if(x=='1')
                return 1;
        else
                return 0;
}

program form decoding:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int hmatrix[3][7]=      {       1,0,0,0,1,1,1,
                                0,1,0,1,0,1,1,
                                0,0,1,1,1,0,1
                        };

int edata[7];
int syndrome[3];
int errdig;

int main()
{
        int i,j;
        system("clear");

        printf("Enter Encoded bits\n");

        for(i=0;i<7;i++)

 
                scanf("%d",&edata[i]);

        for(i=0;i<3;i++)
                for(j=0;j<7;j++)
                        syndrome[i]=syndrome[i]+edata[j]*hmatrix[i][j];

        for(i=0;i<3;i++)
                syndrome[i]=syndrome[i]%2;

        errdig=4*syndrome[0]+2*syndrome[1]+1*syndrome[2];

        if(0==errdig)
                printf("error free data\n");
 else
        {

                printf("error in bit no %d­­­­­ %d\n",errdig,edata[errdig]);
                errdig­­;
                if(1==edata[errdig])
                        edata[errdig]=0;
                else
                        edata[errdig]=1;
        }

        for(i=3;i<7;i++)
                printf("%d",edata[i]);

        puts("");
}
                                                                                                          

              

 
 LEAKY BUCKET ALGORITHM

The leaky­bucket implementation is used to control the rate at which traffic 
is sent to the network. A leaky bucket provides a mechanism by which bursty 
traffic can be shaped to present a steady stream of traffic to the network, as 
opposed to traffic with erratic bursts of low­volume and high­volume flows.

Traffic analogy An appropriate analogy for the leaky bucket is a scenario in 
which four lanes of automobile traffic converge into a single lane. A regulated 

 
admission interval into the single lane of traffic flow helps the traffic move. The 
benefit of this approach is that traffic flow into the major arteries (the network) is 
predictable and controlled. The major liability is that when the volume of traffic is 
vastly greater than the bucket size, in conjunction with the drainage­time interval, 
traffic backs up in the bucket beyond bucket capacity and is discarded.

The Leaky­bucket algorithm

The algorithm can be conceptually understood as follows:
● Arriving packets (network layer PDUs) are placed in a bucket with a hole in 
the bottom. 
● The bucket can queue at most b bytes. If a packet arrives when the bucket is 
full, the packet is discarded. 
● Packets drain through the hole in the bucket, into the network, at a constant 
rate of r bytes per second, thus smoothing traffic bursts. 
The size b of the bucket is limited by the available memory of the system.
Sometimes the leaky bucket and token algorithms are lumped together under the 
same name.

 
EXPERIMENT 9

Write a program for Congestion control using the leaky bucket 
algorithm.

#include<stdio.h>
#include<math.h>
#include<stdlib.h>

int t_rand(int a)
{
 int rn;
 rn=random()%10;
 rn=rn%a;
 if(rn==0)
  rn=1;
 return(rn);
}

int main()
{
        int 
packets[5],i,j,clk,b_size,o_rate,i_rate,p_remain,p_sz_rm=0,p_sz,p_time,flag=0;
         system("clear");
        /* printf("\n Enter 5 packets in the stream:");*/

        for(i=0;i<5;++i)
                packets[i]=t_rand(6)*10;
        /* scanf("%d",&packets[i]);*/
        printf("\n Enter the output rate:");
        scanf("%d",&o_rate);
        printf("\n Enter the Bucket Size:");
        scanf("%d",&b_size);
        for(i=0;i<5;++i)
        {

 
                if((packets[i]+p_sz_rm)>b_size)
                {
                        if(packets[i]>b_size)
                                printf("\n Incoming packet size (%d) is Greater than 
bucket  capacity ­ REJECTED",packets[i]);                        
  else
                                printf("\n Bucket capacity exceeded ­ REJECTED!!");
                }

                else
                {
                        for(j=0;;++j)
                        {
                                p_remain=4­i;
                                p_sz=packets[i];
                                p_sz_rm+=p_sz;
                                printf("\n Incoming Packet sz:%d",p_sz);
                                printf("\n Transmission left:%d",p_sz_rm);

                                p_time=t_rand(4)*10;
                                printf("\n Next Packet Will come at :%d",p_time);

                                for(clk=0;clk<=p_time;clk+=10)
                                {
                                        printf("\n Time Left:%d",p_time­clk);
                                        sleep(1);

                                        if(p_sz_rm)
                                        {
                                                printf(" ­  Transmitted!!");
                                                if(p_sz_rm<=o_rate)
                                                       p_sz_rm=0;
                                                else
                                                       p_sz_rm­=o_rate;
                                                printf(" ­  Bytes Remaining:%d",p_sz_rm);
                                        }
                                        else
                                                printf(" ­  No packets to transmit!!");
                                }

 
                                if(p_sz_rm!=0)
           flag=1;
                                break;
                        }
                }
        }
        printf("\n\n");
        return(0);
}
                                                                        

Você também pode gostar