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

week _________6 to 12

Uploaded by

22211a3232
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views

week _________6 to 12

Uploaded by

22211a3232
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 48

Week 6

NAME OF THE EXPERIMENT: Shortest Path.

AIM: Implement Dijkstra‘s algorithm to compute the Shortest path through a


graph.

HARDWARE REQUIREMENTS: Intel based Desktop PC:- RAM of 512 MB

SOFTWARE REQUIREMENTS: Turbo C / Borland C.

THEORY:

ALGORITHM

Begin

Step1: Declare array path [5] [5], min, a [5][5], index, t[5];

Step2: Declare and initialize st=1,ed=5

Step 3: Declare variables i, j, stp, p, edp

Step 4: print “enter the cost “

Step 5: i=1

Step 6: Repeat step (7 to 11) until (i<=5)

Step 7: j=1

Step 8: repeat step (9 to 10) until (j<=5)


Step 9: Read a[i] [j]

Step 10: increment j

Step 11: increment i

Step 12: print “Enter the path”

Step 13: read p

Step 14: print “Enter possible paths”

Step 15: i=1

Step 16: repeat step(17 to 21) until (i<=p)

Step 17: j=1

Step 18: repeat step(19 to 20) until (i<=5)

Step 19: read path[i][j]

Step 20: increment j

Step 21: increment i

Step 22: j=1

Step 23: repeat step(24 to 34) until(i<=p)

Step 24: t[i]=0

Step 25: stp=st

Step 26: j=1

Step 27: repeat step(26 to 34) until(j<=5)

Step 28: edp=path[i][j+1]

Step 29: t[i]= [ti]+a[stp][edp]

Step 30: if (edp==ed) then

Step 31: break;

Step 32: else


Step 33: stp=edp

Step 34: end if

Step 35: min=t[st]

Step 36: index=st

Step 37: repeat step( 38 to 41) until (i<=p)

Step 38: min>t[i]

Step 39: min=t[i]

Step 40: index=i

Step 41: end if

Step 42: print” minimum cost” min

Step 43: print” minimum cost pth”

Step 44: repeat step(45 to 48) until (i<=5)

Step 45: print path[index][i]

Step 46: if(path[idex][i]==ed) then

Step 47: break

Step 48: end if

End

SOURCE CODE:

//*********************************

//5 .PROGRAM FOR FINDING SHORTEST //PATH FOR A GRAPH

//*********************************

#include<stdio.h>

void main()

{
int path[5][5],i,j,min,a[5][5],p,st=1,ed=5,stp,edp,t[5],index;

printf("enter the cost matrix\n");

for(i=1;i<=5;i++)

for(j=1;j<=5;j++)

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

printf("enter the paths\n");

scanf("%d",&p);

printf("enter possible paths\n");

for(i=1;i<=p;i++)

for(j=1;j<=5;j++)

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

for(i=1;i<=p;i++)

t[i]=0;

for(j=1;j<=5;j++)

edp=path[i][j+1];

t[i]=t[i]+a[stp][edp];

if(edp==ed)

break;

else

stp=edp;

}
min=t[st];index=st;

for(i=1;i<=p;i++)

if(min>t[i])

min=t[i];

index=i;

printf("minimum cost %d",min);

printf("\n minimum cost path ");

for(i=1;i<=5;i++)

printf("--> %d",path[index][i]);

if(path[index][i]==ed)

break;

}
OUTPUT:

enter the cost matrix

12345

12345

12345

12345
12345

enter the paths

enter possible paths

12345

12345

minimum cost 14
week 7

NAME OF THE EXPERIMENT: encrypting DES.

AIM: Take a 64 bit playing text and encrypt the same using DES algorithm.

HARDWARE REQUIREMENTS: Intel based Desktop PC:- RAM of 512 MB

SOFTWARE REQUIREMENTS: Turbo C / Borland C.

THEORY:

Data encryption standard was widely adopted by the industry in security products. Plain
text is

encrypted in blocks of 64 bits yielding 64 bits of cipher text. The algorithm which is
parameterized by a

56 bit key has 19 distinct stages. The first stage is a key independent transposition and
the last stage is

exactly inverse of the transposition. The remaining stages are functionally identical but
are

parameterized by different functions of the key. The algorithm has been designed to
allow decryption

to be done with the same key as encryption

ALGORITHM/FLOWCHART:

Begin

Step1: Initialize as int i,ch,lp;

Step2: Initialize as char cipher[50],plain[50];

Step3: Initialize as char key[50];

Step4: while(1) repeat steps(4-36)

Step5: write "\n-----MENU-----\n"

Step6: write "\n1:Data Encryption\t\n\n2:Data Decryption\t\n\n3:Exit"


Step7: write ("\n\nEnter your choice:"

Step8: read"%d",&ch

Step9: stament switch(ch) repeat steps(9-35)

case 1:

step10: read "\nData Encryption"

step11:read ("\nEnter the plain text:"

step12: fflush(stdin)

step13 : gets(plain)

step14: write "\nEnter the encryption key:"

step15: gets(key)

step16: lp=strlen(key)

step17: Initialize i=0

step18: repeat until plain[i]!='\0'

step19: increment i

step20: initialize cipher[i]=plain[i]^lp

step21: initialize cipher[i]='\0';

step22: write "\nThe encrypted text is:"

step23: puts(cipher)

step24: break

case 2:

step25: write"\nData decryption"

step26: Initialize i=0

step27: repeat until plain[i]!='\0'

step28: increment i
step29: initialize plain[i]=cipher[i]^lp

step30:write"\nDecrypted text is:"

step32: puts(plain)

step33:break

case 3:

step34:exit(0);

step35: end switch stmt

step36: end while(1)stmt

End

SOURCE CODE:

/*Take a 64 bit playing text and encrypt the same using DES algorithm */

#include<stdio.h>

#include<conio.h>

#include<stdlib.h>

#include<string.h>

void main()

int i,ch,lp;

char cipher[50],plain[50];

char key[50];

while(1)

printf("\n-----MENU-----\n");

printf("\n1:Data Encryption\t\n\n2:Data Decryption\t\n\n3:Exit");


printf("\n\nEnter your choice:");

scanf("%d",&ch);

switch(ch)

case 1: printf("\nData Encryption");

printf("\nEnter the plain text:");

fflush(stdin);

gets(plain);

printf("\nEnter the encryption key:");

gets(key);

lp=strlen(key);

for(i=0;plain[i]!='\0';i++)

cipher[i]=plain[i]^lp;

cipher[i]='\0';

printf("\nThe encrypted text is:");

puts(cipher);

break;

case 2: printf("\nData decryption");

for(i=0;cipher[i]!='\0';i++)

plain[i]=cipher[i]^lp;

printf("\nDecrypted text is:");

puts(plain);

break;

case 3: exit(0);
}

getch();

OUTPUT:
Week8:

Implement the AES Encryption and decryption

Data encryption is an important feature in data protection. There are various methods used
to encrypt and decrypt data to enhance the safety of data transmitted.

In this article, we will look at AES as a method of data encryption and decryption.
AES, Advanced Encryption Standard is a block cipher text encryption and decryption
algorithm that processes a block of 128 bits of data using secret keys of 128, 192, or 256
bits.We will also discuss how this algorithm can be implemented using the Java
programming language.

AES is a 128-bit symmetric block ciphertext. This algorithm uses substitution and
permutations; known as the SP networks. It consists of multiple texts to produce a cipher
text. AES performs its calculations in the form of byte data instead of bit data.

This means that AES treats 128 bits of a clear text block as 16 bytes. The number of rounds
during the encryption process depends on the key size being used. For example:

• The 128-bit key size uses 10 rounds.


• The 192-bit key size uses 12 rounds.
• The 256-bit key size uses 14 rounds.

Data to be encrypted is stored in a 4 by 4 matrix format called the state array. Each
output takes a state array as input and gives a similar array as output.

In a 16-bytes matrix, each cell represents 1-byte, this means that four cells which is the
equivalent of four bytes represent one word, implying that each state array has four
words.

The implementation of AES involves doing a set of simple operations repeatedly. Each
repetition is called a "round". Depending on the size of the key (128, 192 or 256 bit), the
input (block of 16 bytes) goes through 10, 12 or 14 rounds. In applying the 2 Big Ideas -
Diffusion and Confusion, AES makes sure that each bit in the 16 byte block depends on
every bit in the same block from 2 rounds previously. That's quite the achievement, so lets
speak about the operations in detail.

Each round consists of 4 steps

1. applying a key – add Round Key()

2. substituting bytes - subBytes()

3. shifting rows - shift Rows()

4. mixing columns - mix Columns()

Decryption involves the inverse of these steps, in reverse order

1. inverse-mixing columns – inv Mix Columns()

2. inverse-shifting rows - invShiftRows()

3. inverse-substituting bytes - invSubBytes()

4. applying a key - addRoundKey()

sourse code

unc encrypt(state, expkey []uint32, rounds int) {


keyi := 0
addRoundKey(state, expkey[keyi:keyi+4])
keyi += 4
for i := 0; i < rounds; i++ {
subBytes(state)
shiftRows(state)
mixColumns(state)
addRoundKey(state, expkey[keyi:keyi+4])
keyi += 4
}
Sub Bytes(state)
Shift Rows(state)
add Round Key(state, expkey[keyi:keyi+4])
}
• The 16-byte block, called state is represented as a slice of 4 4-byte unsigned integers.
The 4-byte unsigned int is also referred to as a "word".
• The expanded key is based on the original key. Its 16*(rounds+1) bytes in length.
Step 1: sub Bytes and inv Sub Bytes
All the 4 operations are invertible. If you took any random 16-byte state and applied any operation and its inverse,
you'd get back the original state. This is how decryption is a simple mirror of the encryption process.

In subBytes each of the 16 bytes is replaced by a byte from the S-box (a lookup table). The code would look
like:

input[i]= sbox[input[i]]// i = 0, 1, ..., 15

For invSubBytes, only the lookup table is changed. The code is input[i] = invsbox[input[i]]. The values
for both lookup tables can be found on the wiki page. If this step appears really simple, its because it is.
Nevertheless, I'd suggest writing a test to check if its working correctly.

• input :=[]uint32{0x8e9ff1c6,0x4ddce1c7,0xa158d1c8,0xbc9dc1c9}
• expected :=[]uint32{0x19dba1b4,0xe386f8c6,0x326a3ee8,0x655e78dd}
Another useful test would be to apply subBytes and invSubBytes on 16 random bytes and check if you get
back the original.

Step 2: shiftRows and invShiftRows

In shiftRows, the rows are shifted left. The top row is left untouched, the second row by 1 byte, the third row
by 2 bytes, the fourth row by 3 bytes. As depictedbelow

• funcshiftRows(state []uint32){
• for i :=1; i <4; i++{
• // rotate word left by specified number of bytes
• state[i]=rotWordLeft(state[i], i)
• }
• }
input :=[]uint32{
0x8e9f01c6,
0x4ddc01c6,
0xa15801c6,
0xbc9d01c6}
expected :=[]uint32{
0x8e9f01c6,
0xdc01c64d,
0x01c6a158,
0xc6bc9d01}

InShift Rows is the inverse operation. The top row is left untouched and the next 3 rows are shifted right by
1, 2, 3 bytes. Again, I'd recommend writing a test to ensure that applying
both shiftRows and invShiftRows to random bytes returns the original.

Step 3: mix Columns and inv MixColumns

This step is slightly complicated, compared to the other 3. The state is operated on column-
wise. Each byte of the column is replaced based on an operation. As you'd expect,
in invMixColumns the 4 bytes are replaced by the 4 original ones.

Speaking about the operation itself, it involves multiplication and addition in the Galois
field. That sounded arcane to me, until I realised that I can get the results of multiplication
via a lookup table and addition is just bit-wise XOR.

// a0-3 represent the bytes of a column from top to bottom

// r0-3 are the transformed bytes


funccalcMixCols(a0, a1, a2, a3 byte)(r0, r1, r2, r3 byte){

// r0 = 2*a0 + 3*a1 + a2 + a3

// r1 = a0 + 2*a1 + 3*a2 + a3

// r2 = a0 + a1 + 2*a2 + 3*a3

// r3 = 3*a0 + a1 + a2 + 2*a3

r0 = gMulBy2[a0]^ gMulBy3[a1]^ a2 ^ a3

r1 = a0 ^ gMulBy2[a1]^ gMulBy3[a2]^ a3

r2 = a0 ^ a1 ^ gMulBy2[a2]^ gMulBy3[a3]

r3 = gMulBy3[a0]^ a1 ^ a2 ^ gMulBy2[a3]

return

funccalcInvMixCols(a0, a1, a2, a3 byte)(r0, r1, r2, r3 byte){

// r0 = 14*a0 + 11*a1 + 13*a2 + 9*a3

// r1 = 9*a0 + 14*a1 + 11*a2 + 13*a3

// r2 = 13*a0 + 9*a1 + 14*a2 + 11*a3

// r3 = 11*a0 + 13*a1 + 9*a2 + 14*a3

r0 = gMulBy14[a0]^gMulBy11[a1]^gMulBy13[a2]^gMulBy9[a3]

r1 = gMulBy9[a0]^gMulBy14[a1]^gMulBy11[a2]^gMulBy13[a3]

r2 = gMulBy13[a0]^gMulBy9[a1]^gMulBy14[a2]^gMulBy11[a3]
r3 = gMulBy11[a0]^gMulBy13[a1]^gMulBy9[a2]^gMulBy14[a3]

return

Each of the gMulBy lookup tables are 256 bytes in size. (You can find them here)

input :=[]uint32{

0xdbf201c6,

0x130a01c6,

0x532201c6,

0x455c01c6}

expected :=[]uint32{

0x8e9f01c6,

0x4ddc01c6,

0xa15801c6,

0xbc9d01c6}

For invMixColumns, the test vectors are simply reversed. As with the other steps, it's a
good idea to check if your mixColumns and invMixColumns invert each other.

I'm not going to explain Galois field arithmetic here for 2 reasons: I'd prefer to keep this
post short, and its not necessary to know exactly how it works whileimplementing AES. I
do recommend reading this book by the creators of AES if you're interested in that or other
interesting topics like cryptanalysis of AES.
Step 4: addRoundKey

The simplest of all the steps. A bit-wise XOR between the 16-byte state and the appropriate 16-bytes of the
expanded key.

funcaddRoundKey(state, key []uint32){

for i :=0; i <4; i++{

state[i]= state[i]^ key[i]

As you probably know, XOR-ing any input with the same key twice returns the original input. That's why
we use the same operation with the same key in both encryption and decryption.

Potential gotcha
Be careful of how you fill the state matrix with your 16 bytes of input.

// wrong

0123

4567

891011

12131415

// correct

04812

15913

261014

371115

EXPERIMENT NO: 9

NAME OF THE EXPERIMENT: RSA.

AIM: Using RSA algorithm encrypt a text data and Decrypt the same.

HARDWARE REQUIREMENTS: Intel based Desktop PC:-RAM of 512 MB


SOFTWARE REQUIREMENTS: Turbo C / Borland C.

THEORY:

RSA method is based on some principles from number theory. In encryption process
divide the

plain text into blocks, so that each plain text message p falls in the interval 0<p<n this can
be done by

grouping the plain text into blocks of k bits. Where k is the largest integer for which 2
power k <n is

true. The security of this method is based on the difficulty of factoring large numbers. The
encryption

and decryption functions are inverses

ALGORITHM/FLOWCHART:

Step1: Start

Step2: Initialize variables as int a,b,i,j,t,x,n,k=0,flag=0,prime[100]

Step3: Initialize variables as char m[20],pp[20]

Step4: Initialize variables as float p[20],c[20]

Step5: Initialize variables as double e,d;

Step6: Initialize i=0

Step7: Repeat step(7-16) until i<50


Step8: Increment i

Step9: Initialize flag=0

Step10: Initialize j=2

Step11: Repeat until j<i/2

Step12: if ‘ i%j == 0 ’ repeat until(12-14)

Step13: Initialize flag=1

Step14: break

Step15: if ’ (flag==0) ‘

Step16: Initialize prime[k++]=i

Step17: Initialize a=prime[k-1]

Step18: Initialize b=prime[k-2]

Step19: Initialize n=a*b

Step20: Initialize t=(a-1)*(b-1)

Step21: Initialize e=(double)prime[2]

Step22: Initialize d=1/(float)e

Step23: write "\nKey of encryption is:%lf\n",d

Step24: write"\nEnter plain the text:"

Step25: read m
Step26: Intialize x=strlen(m)

Step27: write"\nDecryption status From Source to Destination:\n"

Step28: write"\nSource\t->----------------------------------<-destination\n"

Step29: write"\nChar\tnumeric\tcipher\t\tnumeric\t\tchar \n"

Step30:
write"\n***********************************************************\n"

Step31: write"\n"

Step32: Intialize i=0

Step33: repeat steps(33-46) until i<x

Step34: Increment i

Step35: write "%c",m[i]

Step36: write"\t%d",m[i]-97

Step37; Intialize c[i]=pow(m[i]-97,(float)e)

Step38: Initialize c[i]=fmod(c[i],(float)n)

Step39: write "\t%f",c[i]

Step40: Intialize p[i]=pow(c[i],(float)d);

Step41: Intialize p[i]=fmod(p[i],(float)n);

Step42: write "\t%f",p[i]


Step43: Intialize pp[i]=p[i]+97

Step44: write "\t%c\n",pp[i]

Step45: write
"\n***********************************************************\n"

Step46: write "\n"

Step 47 end

SOURCE CODE:

/*Using RSA algorithm encrypt a text data and Decrypt the same*/

#include<stdio.h>

#include<ctype.h>

#include<math.h>

#include<string.h>

void main()

int a,b,i,j,t,x,n,k=0,flag=0,prime[100];

char m[20],pp[20];

float p[20],c[20];

double e,d;
for(i=0;i<50;i++)

flag=0;

for(j=2;j<i/2;j++)

if(i%j==0)

flag=1;

break;

if(flag==0)

prime[k++]=i;

a=prime[k-1];

b=prime[k-2];

n=a*b;

t=(a-1)*(b-1);

e=(double)prime[2];

d=1/(float)e;
printf("\nKey of encryption is:%lf\n",d);

printf("\nEnter plain the text:");

scanf("%s",&m);

x=strlen(m);

printf("\nDecryption status From Source to Destination:\n");

printf("\nSource\t->----------------------------------<-destination\n");

printf("\nChar\tnumeric\tcipher\t\tnumeric\t\tchar \n");

printf("\n***********************************************************\n");

printf("\n");

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

printf("%c",m[i]);

printf("\t%d",m[i]-97);

c[i]=pow(m[i]-97,(float)e);

c[i]=fmod(c[i],(float)n);

printf("\t%f",c[i]);

p[i]=pow(c[i],(float)d);

p[i]=fmod(p[i],(float)n);
printf("\t%f",p[i]);

pp[i]=p[i]+97;

printf("\t%c\n",pp[i]);

printf("\n***********************************************************\n");

printf("\n");

OUTPUT:
WEEK – 10

Study of Socket Programming and Client–Server model.

AIM:

To study about Socket Programming and Client - Server model under UNIX operating
systems.

DESCRIPTION:

Socket A socket is formally defined as an endpoint for communication between an


application program, and the underlying network protocols

The two modes of services available are

Connection-oriented service

Connection less service

Connectionless (UDP) vs Connection-Oriented (TCP) Servers

Programmer can choose a connection-oriented server or a connectionless server based on


their applications.

In Internet Protocol terminology, the basic unit of data transfer is a datagram. This
is basically a header followed by some data. The datagram socket is connectionless.

User Datagram Protocol (UDP):


1.Is a connectionless.

2.A single socket can send and receive packets from many different computers.

3.Best effort delivery.4.Some packets may be lost some packets may arrive out of order.

Transmission Control Protocol (TCP):

1.Is a connection-oriented.

2.A client must connect a socket to a server.

3.TCP socket provides bidirectional channel between client and server.

4.Lost data is re-transmitted.5.Data is delivered in-order.6.Data is delivered as a stream of


bytes.

7.TCP uses flow control.

What is socket programming?


Socket programming is a way of connecting two nodes on a network to communicate
with each other. One socket(node) listens on a particular port at an IP, while the other
socket reaches out to the other to form a connection. The server forms the listener socket
while the client reaches out to the server.
State diagram for server and client model

Stages for server

1. Socket creation:

int sockfd = socket(domain, type, protocol)


• sockfd: socket descriptor, an integer (like a file-handle)
• domain: integer, specifies communication domain. We use AF_ LOCAL as defined
in the POSIX standard for communication between processes on the same host. For
communicating between processes on different hosts connected by IPV4, we use
AF_INET and AF_I NET 6 for processes connected by IPV6.
type: communication type
SOCK_STREAM: TCP(reliable, connection oriented)
SOCK_DGRAM: UDP(unreliable, connectionless)

protocol: Protocol value for Internet Protocol(IP), which is 0. This is the same number
which appears on protocol field in the IP header of a packet.(man protocols for more
details)

2. Setsockopt: This helps in manipulating options for the socket referred by the file
descriptor sockfd. This is completely optional, but it helps in reuse of address and port.
Prevents error such as: “address already in use”.

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

3. Bind:

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

After creation of the socket, bind function binds the socket to the address and port
number specified in addr(custom data structure). In the example code, we bind the server
to the localhost, hence we use INADDR_ANY to specify the IP address.

4. Listen:

int listen(int sockfd, int backlog);

It puts the server socket in a passive mode, where it waits for the client to approach the
server to make a connection. The backlog, defines the maximum length to which the
queue of pending connections for sockfd may grow. If a connection request arrives when
the queue is full, the client may receive an error with an indication of
ECONNREFUSED.

5. Accept:

int new_socket= accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

It extracts the first connection request on the queue of pending connections for the
listening socket, sockfd, creates a new connected socket, and returns a new file descriptor
referring to that socket. At this point, connection is established between client and server,
and they are ready to transfer data.

Stages for Client

• Socket connection: Exactly same as that of server’s socket creation


• Connect: The connect() system call connects the socket referred to by the file
descriptor sockfd to the address specified by addr. Server’s address and port is
specified in addr.

Implementation
Here we are exchanging one hello message between server and client to demonstrate
the client/server model.

Server.c

// Server side C/C++ program to demonstrate Socket

// programming

#include <netinet/in.h>
#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/socket.h>

#include <unistd.h>

#define PORT 8080

intmain(intargc, charconst* argv[])

intserver_fd, new_socket, valread;

structsockaddr_in address;

intopt = 1;

intaddrlen = sizeof(address);

charbuffer[1024] = { 0 };

char* hello = "Hello from server";

// Creating socket file descriptor

if((server_fd = socket(AF_INET, SOCK_STREAM, 0))

== 0) {

perror("socket failed");

exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080

if(setsockopt(server_fd, SOL_SOCKET,

SO_REUSEADDR | SO_REUSEPORT, &opt,

sizeof(opt))) {

perror("setsockopt");

exit(EXIT_FAILURE);

address.sin_family = AF_INET;

address.sin_addr.s_addr = INADDR_ANY;

address.sin_port = htons(PORT);

// Forcefully attaching socket to the port 8080

if(bind(server_fd, (structsockaddr*)&address,

sizeof(address))

< 0) {

perror("bind failed");

exit(EXIT_FAILURE);

}
if(listen(server_fd, 3) < 0) {

perror("listen");

exit(EXIT_FAILURE);

if((new_socket

= accept(server_fd, (structsockaddr*)&address,

(socklen_t*)&addrlen))

< 0) {

perror("accept");

exit(EXIT_FAILURE);

valread = read(new_socket, buffer, 1024);

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

send(new_socket, hello, strlen(hello), 0);

printf("Hello message sent\n");

// closing the connected socket

close(new_socket);

// closing the listening socket

shutdown(server_fd, SHUT_RDWR);
return0;

client.c

/ Client side C/C++ program to demonstrate Socket

// programming

#include <arpa/inet.h>

#include <stdio.h>

#include <string.h>

#include <sys/socket.h>

#include <unistd.h>

#define PORT 8080

intmain(intargc, charconst* argv[])

intsock = 0, valread, client_fd;

structsockaddr_in serv_addr;

char* hello = "Hello from client";

charbuffer[1024] = { 0 };

if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {


printf("\n Socket creation error \n");

return-1;

serv_addr.sin_family = AF_INET;

serv_addr.sin_port = htons(PORT);

// Convert IPv4 and IPv6 addresses from text to binary

// form

if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)

<= 0) {

printf(

"\nInvalid address/ Address not supported \n");

return-1;

if((client_fd

= connect(sock, (structsockaddr*)&serv_addr,

sizeof(serv_addr)))

< 0) {
printf("\nConnection Failed \n");

return-1;

send(sock, hello, strlen(hello), 0);

printf("Hello message sent\n");

valread = read(sock, buffer, 1024);

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

// closing the connected socket

close(client_fd);

return0;

Compiling:

gcc client.c -o client

gcc server.c -o server

Output:

Client:Hello message sent


Hello from server
Server:Hello from client
Hello message sent
WEEK – 11

Week11: Write a socket program (usingc)for interaction between server and client processes
using Unix Domain sockets.

client1.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
int main(void)

struct sockaddr_un address;

int socket_fd, nbytes;

char buffer[256];

socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);

if(socket_fd < 0)

printf("socket() failed\n");

return 1;

}
/* start with a clean address structure */

memset(&address, 0, sizeof(struct sockaddr_un));

address.sun_family = AF_UNIX;

snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");


if(connect(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0)

printf("connect() failed\n");

return 1;

nbytes = snprintf(buffer, 256, "hello from a client");

write(socket_fd, buffer, nbytes);

nbytes = read(socket_fd, buffer, 256);

buffer[nbytes] = 0;

printf("MESSAGE FROM SERVER: %s\n", buffer);

close(socket_fd);

return 0;

server1.c:
#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/socket.h>

#include <sys/un.h>

int connection_handler(int connection_fd)

{
int n bytes;

char buffer[256];

nbytes = read(connection_fd, buffer, 256);

buffer[nbytes] = 0;

printf("MESSAGE FROM CLIENT: %s\n", buffer);

nbytes = snprintf(buffer, 256, "hello from the server");

write(connection_fd, buffer, nbytes);

close(connection_fd);

return 0;

int main(void)

struct sockaddr_un address;

int socket_fd, connection_fd;

socklen_t address_length;

pid_t child;

socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);

if(socket_fd < 0)

printf("socket() failed\n");
return 1;

unlink("./demo_socket");
* start with a clean address structure */

memset(&address, 0, sizeof(struct sockaddr_un));

address.sun_family = AF_UNIX;

snprintf(address.sun_path, UNIX_PATH_MAX, "./demo_socket");

if(bind(socket_fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0)

printf("bind() failed\n");

return 1;

if(listen(socket_fd, 5) != 0)

printf("listen() failed\n");

return 1;

while((connection_fd = accept(socket_fd, (struct sockaddr *) &address,


&address_length)) > -1)

child = fork();

if(child == 0)
{
/* now inside newly created connection handling process */

return connection_handler(connection_fd);

/* still inside server process */

close(connection_fd);

close(socket_fd);

unlink("./demo_socket");

return 0;

}
Experiment – 12

Week12: Write a socket program(using c)for interaction between server and client processes using
Internet Domain sockets.

Socket Creation The socket() call creates a socket, s = socket(domain, type, protocol); in
the specified domain and of the specified type. If the protocol is unspecified (a value of
0), the system selects a protocol that supports the requested socket type. The socket handle
(a file descriptor) is returned. The domain is specified by one of the constants defined in .
For the UNIX domain the constant is AF_UNIX. For the Internet domain it is AF_INET.
Constants named AF_ specify the address format to use in interpreting names. Socket
types are defined in . SOCK_STREAM, SOCK_DGRAM, or SOCK_RAW is supported
by AF_INET and AF_UNIX. The following creates a stream socket in the Internet
domain: s = socket(AF_INET, SOCK_STREAM, 0); This call results in a stream socket
with the TCP protocol providing the underlying communication. A datagram socket for
intramachine use is created by: s = socket(AF_UNIX, SOCK_DGRAM, 0);

Binding Local Names A socket is created with no name. A remote process has no way to
refer to a socket until an address is bound to it. Communicating processes are connected
through addresses. In the Internet domain, a connection is composed of local and remote
addresses, and local and remote ports. In the UNIX domain, a connection is composed of
(usually) one or two path names. In most domains, connections must be unique.

In the Internet domain, there may never be duplicate ordered sets, such as: . UNIX domain
sockets need not always be bound to a name, but when bound there may never be duplicate
ordered sets such as: . The path names may not refer to existing files. The bind() call
allows a process to specify the local address of the socket. This forms the set (or ) while
connect() and accept() complete a socket’s association. The bind() system call is used as
follows: bind (s, name, namelen); s is the socket handle. The bound name is a byte string
that is interpreted by the supporting protocol(s). Internet domain names contain an Internet
address and port number. UNIX domain names contain a path name and a family. Code
Example 2-1 binds the name /tmp/foo to a UNIX domain socket. Code Example 2-1 Bind
Name to Socket #include ... struct sockaddr_un addr; ... strcpy(addr.sun_path, "/tmp/foo");
addr.sun_family = AF_UNIX; bind (s, (struct sockaddr *) &addr, strlen(addr.sun_path) +
sizeof (addr.sun_family)); Note that in determining the size of an AF_UNIX socket
address, null bytes are not counted, which is why strlen() use is fine. The file name referred
to in addr.sun_path is created as a socket in the system file name space. The caller must
have write permission in the directory where addr.sun_path is created. The file should be
deleted by the caller when it is no longer needed. AF_UNIX sockets can be deleted with
unlink(). Binding an Internet address is more complicated. The call is similar:

#include #include

...

struct sockaddr_in sin;

...

bind (s, (struct sockaddr *) &sin, sizeof sin);

Connection Establishment Connection establishment is usually asymmetric, with one


process acting as the client and the other as the server. The server binds a socket to a well-
known address associated with the service and blocks on its socket for a connect request.
An unrelated process can then connect to the server. The client requests services from the
server by initiating a connection to the server’s socket. On the client side, the connect()
call initiates a connection. In the UNIX domain, this might appear as: struct sockaddr_un
server; server.sun.family = AF_UNIX; ... connect(s, (struct sockaddr *)&server,
strlen(server.sun_path) + sizeof (server.sun_family)); while in the Internet domain it
might be: struct sockaddr_in server; ... connect(s, (struct sockaddr *)&server, sizeof
server); If the client’s socket is unbound at the time of the connect call, the system
automatically selects and binds a name to the socket. See “Signals and Process Group ID”
on page 45. This is the usual way that local addresses are bound to a socket on the client
side. In the examples that follow, only AF_INET sockets are described. To receive a
client’s connection, a server must perform two steps after binding its socket. The first is
to indicate how many connection requests can be queued. The second step is to accept a
connection:

struct sockaddr_in from;

...

listen(s, 5); /* Allow queue of 5 connections */

fromlen = sizeof(from);

newsock = accept(s, (struct sockaddr *) &from, &fromlen);

Closing Sockets A SOCK_STREAM socket can be discarded by a close() system call. If


data is queued to a socket that promises reliable delivery after a close(), the protocol
continues to try to transfer the data. If the data is still undelivered after an arbitrary period,
it is discarded.

shutdown() closes SOCK_STREAM sockets gracefully. Both processes can acknowledge


that they are no longer sending. This call has the form: shutdown(s, how); where how is 0
disallows further receives, 1 disallows further sends, and 2 disallows both.

// server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

#define PORT 8080


#define BUFFER_SIZE 1024

int main() {
int server_socket, new_socket;
struct sockaddr_in server_addr, client_addr;
int opt = 1;
int addrlen = sizeof(server_addr);
char buffer[BUFFER_SIZE] = {0};

// Creating socket file descriptor


if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}

// Forcefully attaching socket to the port 8080


if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR |
SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}

server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);

// Forcefully attaching socket to the port 8080


if (bind(server_socket, (struct sockaddr*)&server_addr,
sizeof(server_addr)) < 0) {
perror("Bind failed");
exit(EXIT_FAILURE);
}

if (listen(server_socket, 3) < 0) {
perror("Listen failed");
exit(EXIT_FAILURE);
}

printf("Server listening on port %d...\n", PORT);

if ((new_socket = accept(server_socket, (struct sockaddr*)&client_addr,


(socklen_t*)&addrlen)) < 0) {
perror("Accept failed");
exit(EXIT_FAILURE);
}

printf("Connection accepted from %s:%d\n",


inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

// Read and send data


read(new_socket, buffer, BUFFER_SIZE);
printf("Client: %s\n", buffer);

const char *server_message = "Hello from server!";


send(new_socket, server_message, strlen(server_message), 0);
printf("Message sent to client.\n");

close(new_socket);
close(server_socket);

return 0;
}

// client.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>

#define PORT 8080


#define BUFFER_SIZE 1024

int main() {
int client_socket;
struct sockaddr_in server_addr;
char buffer[BUFFER_SIZE] = {0};

// Creating socket file descriptor


if ((client_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}

server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);

// Convert IPv4 and IPv6 addresses from text to binary form


if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
perror("Invalid address/ Address not supported");
exit(EXIT_FAILURE);
}

if (connect(client_socket, (struct sockaddr*)&server_addr,


sizeof(server_addr)) < 0) {
perror("Connection Failed");
exit(EXIT_FAILURE);
}

const char *message = "Hello from client!";


send(client_socket, message, strlen(message), 0);
printf("Message sent to server.\n");

// Read server response


read(client_socket, buffer, BUFFER_SIZE);
printf("Server: %s\n", buffer);

close(client_socket);

return 0;
}

You might also like