30 things Girls Think Guys Should Know
1. Don't ever lie to us; we always find out.
2. We don't enjoy talking dirty to you as much as you enjoy listening.
3. Don't say you understand when you don't.
4. Girls are petty; get over it.
5. You don't have PMS; don't act like you know what it's like.
6. Saying something sweet might get you off the hook; doing something sweet will always get you off the hook.
7. If you talk about having a big dick; we know you don't.
8. Size does matter.
9. We don't like it when you act like Mr. Big; we like it when you are Mr. Big.
10. A system in your car only impresses your homeboys.
11. No matter what you say, your ex-girlfriend is a ho.
12. It's good to be sensitive, sometimes.
13. If you did something wrong or even if you didn't, apologize.
14. Be spontaneous; dinner and a movie won't always cut it.
15. We are self-conscious by nature; we can't help it.
16. We are drama queens.
17. Fashion police do exist.
18. Don't ask us to give head; if you are nice you just might get it.
19. We absolutely do not care about monster trucks, car systems, paintball, or anything else you and your friends talk about.
20. Hugs and kisses must be given at all times.
21. We don't shave our legs every day; get over it.
22. Don't make bets about us; we always find out.
23. Shave; no matter how cool you think it looks, we hate it.
24. Even is you think it is cool to burp, fart, or emit other strange gases from your body, it is not.
25. Don't compare our breasts with Pamela Anderson's; hers are fake.
26. It is not cool to shoot snot rockets.
27. We are beautiful, but make-up helps.
28. We will always think we are fat, so humor us and tell us we aren't.
29. You can shoot hoops, score a goal, knock down big fat guys, and hit a little baseball with a stick, so why the hell can't you piss in the toilet and not on it.
30. Most importantly: we are always right; so don't forget it.
Friday, December 19, 2008
top most reply of a girl, when you propose her...
top most reply of a girl, when you propose her...
Here are the top most reply of a girl, when you propose her...
1) Nahi........ ......... ???
2) Chiiiii..... Kitne gande vichar hain tumhare..... ..
3) Maine tumhe sirf ek acche dost ki nazar se dekha hai ....
4) Mera pehle se ek boyfrnd hai....
5) Main in baton pe vishwas nahi karti, apne padhai pe dhyaan lagao...
6) tum abhi tak mujhe jaante kahan ho ?Yeh shayad infatuation hai....
7) Tumhara bank balance kitna hai…??
8) Magar last year to Maine tumhe raakhi baandhi thi ..hai
naa..bhaiyya. .??
9) Mein abhi is relation ke liye mentally prepared nahi hoo....
10) Mein apne dady se pooch ke tumhe kaal answer karu…??
11) Itni is baat kehne ke liye itni der lagaa di??
12) Ye donon ke dil me hai na, to phir kya kehna!!
13) Sorry
14) "……Apna chehra kabhi aayine me dekha hai….. L………… "
15) "Main toh tumhe apna Bhai maanati hu"
16) "Yes .. I too like you … (but hope you don't cheat on me ) " …
(Which guys most oftenly do )
17) Phele kyon nahi bataya AB tum late ho gaye ..
18) Tum agar pehle mile hote to sochti.
19) Tumhari himmat kaise hui mere baare mein aisa sochne ki…
(probably followed by a slap)
20) Girl: mujhe sochna ka wakt do…
Guy: kitna wakt???(with hope)
Girl: saat janam
21) Mai ek shaadi shuda ladki hu ;-)
22) Mein tumhare chotte bhai se pyaar karti hoon…
23) Now that's a real tragedy….
Girl: Hee hee ……hee hee hee…..hee ….hee……hee…… Hee hee ……hee hee
hee…..hee ….hee……hee……
24) Boy: I love U!
Gal: I don't think ABT all this before marriage.
25) Keep loving I don't care.
26) Tum mere liye kya kar sakte ho…
27) Kaun as number hai mera tumhare proposals ki history mein. Ha
ha ha ha….
28) tumhe is nazar se kabhi dekha nahi
29) tumhare barre mein kabhi aisa socha nahi
30) mummy se pooch kar bataungi
31) mere bhaiyya se baat kar lo , who hi tumhe samajhayenge
32) Knyo, Tina NE "No" bola?
33) Lekin tum to Mina ke piche pade the, Kya usne thappad mara?
34) Kitne time ke liye -???
35) Worst one-- Jo bhi bolna hai jaldi bolo mera beta school se aata
hoga..
36) Thanks. I love you, too.
37) Boy :- Sonya, I love U…..
Gal :- Sorry , Next 3 Months tak Waiting List chal rahi hai….
38) "What?"
39) "Let's just stay away from this"
40) My friend in college got one classic reply … "I THINK I'M
ENGAGED"
41) "I think, I will have better options in future ..."
42)Mujhe tumse is baare mein koi baat nahi karni, then she starts
ignoring, phir bhi nahi sudhare then she threatens via some common
friends.
43) My Boy friend is very short Tempered. Beware of it.
44) like you as a friend but I never thought about us like this…cant
we be just good friends for ever
45) Actually my younger sis likes you a lot. ..
46) My mummy does not like your family (if the family knows each
other.) ..
47) "Why me?..Tumne mere meih essa kya dekha?..."she wants you to
list down all the Good qualities that you even might have not seen in
her. ...
48) SLAP !! ACTIONS SPEAK LOUDER THAN WORDS....it is said ..
49)hehe I didn't expect that from you....
50)nice joke ...
51)tum ladke kuchh or nahi soch sakte jaha ladki dekhi fisal
gaye.....
52)achha tum bhi meine socha sirf harsh,nikhil, ravi, etc etc ko hi
mujhme interest hai ..... And then walks on.......... ...
53)tumhe to purpose karna bhi nahi aata.... Peheli bari hai kya?? Koi
baat nahi mein batati Hun ???...
Here are the top most reply of a girl, when you propose her...
1) Nahi........ ......... ???
2) Chiiiii..... Kitne gande vichar hain tumhare..... ..
3) Maine tumhe sirf ek acche dost ki nazar se dekha hai ....
4) Mera pehle se ek boyfrnd hai....
5) Main in baton pe vishwas nahi karti, apne padhai pe dhyaan lagao...
6) tum abhi tak mujhe jaante kahan ho ?Yeh shayad infatuation hai....
7) Tumhara bank balance kitna hai…??
8) Magar last year to Maine tumhe raakhi baandhi thi ..hai
naa..bhaiyya. .??
9) Mein abhi is relation ke liye mentally prepared nahi hoo....
10) Mein apne dady se pooch ke tumhe kaal answer karu…??
11) Itni is baat kehne ke liye itni der lagaa di??
12) Ye donon ke dil me hai na, to phir kya kehna!!
13) Sorry
14) "……Apna chehra kabhi aayine me dekha hai….. L………… "
15) "Main toh tumhe apna Bhai maanati hu"
16) "Yes .. I too like you … (but hope you don't cheat on me ) " …
(Which guys most oftenly do )
17) Phele kyon nahi bataya AB tum late ho gaye ..
18) Tum agar pehle mile hote to sochti.
19) Tumhari himmat kaise hui mere baare mein aisa sochne ki…
(probably followed by a slap)
20) Girl: mujhe sochna ka wakt do…
Guy: kitna wakt???(with hope)
Girl: saat janam
21) Mai ek shaadi shuda ladki hu ;-)
22) Mein tumhare chotte bhai se pyaar karti hoon…
23) Now that's a real tragedy….
Girl: Hee hee ……hee hee hee…..hee ….hee……hee…… Hee hee ……hee hee
hee…..hee ….hee……hee……
24) Boy: I love U!
Gal: I don't think ABT all this before marriage.
25) Keep loving I don't care.
26) Tum mere liye kya kar sakte ho…
27) Kaun as number hai mera tumhare proposals ki history mein. Ha
ha ha ha….
28) tumhe is nazar se kabhi dekha nahi
29) tumhare barre mein kabhi aisa socha nahi
30) mummy se pooch kar bataungi
31) mere bhaiyya se baat kar lo , who hi tumhe samajhayenge
32) Knyo, Tina NE "No" bola?
33) Lekin tum to Mina ke piche pade the, Kya usne thappad mara?
34) Kitne time ke liye -???
35) Worst one-- Jo bhi bolna hai jaldi bolo mera beta school se aata
hoga..
36) Thanks. I love you, too.
37) Boy :- Sonya, I love U…..
Gal :- Sorry , Next 3 Months tak Waiting List chal rahi hai….
38) "What?"
39) "Let's just stay away from this"
40) My friend in college got one classic reply … "I THINK I'M
ENGAGED"
41) "I think, I will have better options in future ..."
42)Mujhe tumse is baare mein koi baat nahi karni, then she starts
ignoring, phir bhi nahi sudhare then she threatens via some common
friends.
43) My Boy friend is very short Tempered. Beware of it.
44) like you as a friend but I never thought about us like this…cant
we be just good friends for ever
45) Actually my younger sis likes you a lot. ..
46) My mummy does not like your family (if the family knows each
other.) ..
47) "Why me?..Tumne mere meih essa kya dekha?..."she wants you to
list down all the Good qualities that you even might have not seen in
her. ...
48) SLAP !! ACTIONS SPEAK LOUDER THAN WORDS....it is said ..
49)hehe I didn't expect that from you....
50)nice joke ...
51)tum ladke kuchh or nahi soch sakte jaha ladki dekhi fisal
gaye.....
52)achha tum bhi meine socha sirf harsh,nikhil, ravi, etc etc ko hi
mujhme interest hai ..... And then walks on.......... ...
53)tumhe to purpose karna bhi nahi aata.... Peheli bari hai kya?? Koi
baat nahi mein batati Hun ???...
Thursday, December 18, 2008
TELNET
Documents to read:
Manuals of telnetd(8),telnet(1),issue.net(5),tcpd(8)
and hosts_access(5).
Square brackets are used to separate keywords, such as filenames,
programs names etc etc from lines of text. They have no other meaning.
A TELNET server, with minimal configuration, is to be used in this
experiment.
Create a directory named [telnet], in your home directory.
$ cd <-- puts you in your [home] directory
$ mkdir telnet
$ cd telnet
Installations are to be carried out from this directory. Binary
packages are to be installed. It is also possible to compile from
source code. Such source code may be down-loaded from Internet.
This experiment is to be carried out in Debian Linux platform. Some
Debian specific commands such as [dpkg], [dselect] etc etc have to be
used for software installation and removal. Other distributions have
similar commands of their own. Redhat Linux used [rpm] command.
The following command lists the softwares installed in your host.
$ dpkg -l
The output may be examined one screen at time
$ dpkg -l | more
If the name of the software is known partially it may be checked
$ dpkg -l | grep pyth
Find out the [telnet] related softwares installed in your host
$ dpkg -l | grep telnet
Typical output might be:
ii telnet 0.17-18woody2 The telnet client.
ii telnetd 0.17-18woody2 The telnet server.
The above lines indicate that [telnet] client and [telnet] servers are
installed in your host.
The status of the installed software can be checked.
Check the status of [telnet] client program. Output is not shown.
$ dpkg --status telnet
Check the status of [ telnetd ]. This is the server program. Output is
not shown.
$ dpkg --status telnetd
Test [telnetd] and [telnet] programs in your host
$ telnet 127.0.0.1
You may login in any user account if password is known.
As this experiment is on installation, the installed packages are to
be removed and then reinstalled.
Note: Installation and removal of software needs [root] privilege.
Remove the TELNET client program [telnet]
# dpkg -r telnet
Now the following command should fail
$ telnet 127.0.0.1
Check the [telnet] related installed packages.
$ dpkg -l | grep telnet
Output might be:
rc telnet 0.17-18woody2 The telnet client.
ii telnetd 0.17-18woody2 The telnet server.
The [ telnet ] program was removed but its configuration file was not
removed. Remove the configuration file.
# dpkg --purge telnet
Check the [telnet] related installed packages.
$ dpkg -l | grep telnet
Output might be:
ii telnetd 0.17-18woody2 The telnet server.
Check the status of [telnet] client program. Output is not shown.
$ dpkg --status telnet
Remove TELNET server program with its configuration file/files.
# dpkg --purge telnetd
Check the [telnet] related installed packages.
$ dpkg -l | grep telnet
Copy [ telnet ] and [ telnetd ] binary packages in your [ telnet ]
directory. You may use NFS or FTP for copying.
The package names might be
telnet_0.17-18woody2_i386.deb
and telnetd_0.17-18woody2_i386.deb
Note: The files are also available in first CD of a set of seven CDs.
These CDs are kept in the laboratory.
Install the TELNET client program
# dpkg -i telnet_0.17-18woody2_i386.deb
Check status of [telnet]
$ dpkg --status telnet
At present the TELNET client program is installed. Next command should
fail, as there is no TELNET server running on this host
$ telnet 127.0.0.1
However the client program can be used to access TELNET server running
on other host. Replace 192.16.5.251 with a suitable address.
$ telnet 192.16.5.251
Install the TELNET server program
# dpkg -i telnetd_0.17-18woody2_i386.deb
Check status of [telnetd]
$ dpkg --status telnetd
Find out where the executable(binary) of [telnetd] is installed
$ whereis -b in.telnetd
Location of [in.telnetd] -->
Briefly read manual of the TELNET server
$ man 8 telnetd
From the manual we find that the file [/etc/issue.net] is a text file
which contains a message or system identification to be printed before
the login prompt of a [telnet] session.
To know about the syntax of the file [ /etc/issue.net ], its manual is
consulted.
$ man 5 issue.net
A new [ issue.net ] is to be prepared, to provide the following to a
[telnet] client:
Welcome message
System node name (FQDN)
Current time and date
Name of the operating system and OS release name
Machine (hardware) type
Before modification, the original file is saved with a distinctive
extension for later identification.
$ cp /etc/issue.net ./issue.net-$USER-$( /bin/date +%H-%M )
Note the name of the saved file
$ ls -l | grep issue
Name of saved file-->
Edit [/etc/issue.net]
# nano /etc/issue.net
The file should contain the following text. Replace Sumit with your
name.
-------- /etc/issue.net --------
Welcome to Sumit's TELNET server
Terminal -----> %t
Server name --> %h
Date & time --> %d
OS -----------> %s %r
Hardware -----> %m
--------------------------------
Save the file.
Request two of your friends to [telnet] to your host. 192.169.5.146 is
assumed to be your IP address.
friend1 $ telnet 192.169.5.146
friend2 $ telnet 192.169.5.146
They should get the above information.
A server program may be kept running on a host. Such servers are
called stand-alone servers. Frequently used servers, such as [ named ]
( name server ), [ exim ] ( mail server ) run as stand-alone servers.
Less frequently used servers such as [ date ], [ echo ] etc etc do not
run always. A master server called [inetd] runs always. When a request
for a less frequently used server such as [date] comes, [inetd] starts
the [ date ] server. Usually [ telnetd ] is started by [inetd].
Note: [ date ], [ echo ] are two of the trivial services provided
internally by [ inetd ].
Note: [ xinetd ] is another master server with more functionality than
[ inetd ].
Examine file [ /etc/inetd.conf ] to find out if [ telnetd ] is started
by [inetd].
$ less /etc/inetd.conf
Was there any entry for [telnet] service ( Y / N )
A typical entry for [telnet] service is shown
telnet stream tcp nowait telnetd.telnetd /usr/sbin/tcpd /usr/sbin/in.telnetd
Note: The entry must be on a SINGLE line. A comment ( hash ) before a
service name, disables the service.
The [telnetd] is to be disabled using file [ /etc/inetd.conf ]
Edit file [ /etc/inetd.conf ]
# nano /etc/inetd.conf
Put a hash ( # ) mark before [telnet] service name and save the file.
Try to [telnet] to localhost.
$ telnet 127.0.0.1
This should succeed in spite of the hash before the service name. The
[inetd] process is not yet aware of the modifications made by you. If
SIGHUP signal is delivered to [ inetd ] process, its signal handler
makes arrangement to re-read its configuration file. [/etc/inetd.conf]
is the configuration file of [inetd] process.
Find out PID of [inetd] daemon process
$ ps ax | grep inetd
PID-of-inetd-->
Send SIGHUP signal to [ inetd ] daemon, to re-read [ /etc/inetd.conf ]
# kill -SIGHUP pid-of-inetd
Try to [telnet] to localhost. Now it should fail
$ telnet 127.0.0.1
Describe the steps to enable TELNET service.
Again examine the following line from [ /etc/inetd.conf ] file.
telnet stream tcp nowait telnetd.telnetd /usr/sbin/tcpd /usr/sbin/in.telnetd
The field [ /usr/sbin/tcpd ] indicates that access to [telnet] service
is controlled by [tcpd].
Access control to your host with [tcpd]:
[tcpd] program can be used to
control access to some of the services offered by your host, with two
files:
[ /etc/hosts.allow ] and [ /etc/hosts.deny ]
For access control to be effective, [tcpd] must be called first to get
the service. Check file [ /etc/inetd.conf ] to find out the services
controlled by [tcpd]. You may read manual of [tcpd(8)].
The access control software consults [/etc/hosts.allow] first and then
[/etc/hosts.deny]. The search stops at the first match. If no match is
found in either of the files, access is granted. To know about access
control rules you may read manual [hosts_access(5)].
Note: If extended access control rules are used, it is possible to use
a single access control file such as [/etc/hosts.allow].
You may read manual of hosts_options(5).
Case-1: Access is open:
The two files [/etc/hosts.allow] and
[/etc/hosts.deny] may be absent or may be present without any
rule.
OR
If the line:
ALL : ALL
is entered in [/etc/hosts.allow]. File [/etc/hosts.deny] would
not be consulted in this case, as file [ /etc/hosts.allow ] is
checked first.
Case-2: Access is mostly open and access is denied on specific cases.
File [/etc/hosts.allow] may be absent or empty of rules. File
[/etc/hosts.deny] blocks access specifically.
Example:
Edit the file [/etc/hosts.deny]
# nano /etc/hosts.deny
Add the following line in that file
in.telnetd : sumit@127.0.0.1
Save the file.
The above line deny access to user [sumit] to [telnet]
service from host 127.0.0.1 ( localhost ).
Login as [sumit] and [telnet] to localhost
sumit $ telnet 127.0.0.1
Was it successful ? ( y / N )
Login as [you] and [telnet] to localhost
you $ telnet 127.0.0.1
Was it successful ? ( Y / n )
Case-3: Access is mostly closed and access is granted on specific
cases.
Note: Paranoid System Administrators might use this scheme
The file [/etc/hosts.deny] contains a single line
ALL : ALL
This line denies access to all. As [ /etc/hosts.allow ] is
checked first, specific cases are granted access in that file.
Example:
Edit the file [/etc/hosts.deny] and add a single line
All : ALL
Save the file.
Edit [/etc/hosts.allow] and keep it blank.
Try to [telnet] to localhost as [sumit], [you],[guest]
or any other user
Were these successful ? ( y / N )
Edit [/etc/hosts.allow] and add the following line in
that file
in.telnetd : sumit@127.0.0.1
Save the file.
Try to [telnet] to localhost as [sumit]
sumit $ telnet 127.0.0.1
Was it successful ? ( Y / n )
Try to [telnet] to localhost as [you], [guest] or any
user other than [sumit]
Were these successful ? ( y / N )
Assignment-1:
Configure your host as a mostly closed system using
[tcpd] and allow:
a. [telnet] access from 172.16.2.0 network.
b. Access to all services from localhost (127.0.0.1)
Enter suitable entries in the two files
------- /etc/hosts.allow ---------
----------------------------------
--- /etc/hosts.deny ---
ALL : ALL
-----------------------
The following steps were followed to install TELNET server
1. The binary package of [telnetd] was installed
# dpkg -i telnetd_0.17-18woody2_i386.deb
2. The file [/etc/issue.net] was modified to provide some information
to the [telnet] clients.
3.
(a) Hash before [ telnet ] service line in [ /etc/inetd ] file was
removed.
(b) PID of [inetd] super-server was determined.
(c) SIGHUP signal was sent to [inetd] daemon process.
4. Mostly closed [tcpd] access control was imposed.
(a) ALL : ALL was entered in [/etc/hosts.allow] file.
(b) The file [/etc/hosts.allow] was modified as under
--------------------------------------
in.telnetd : 172.16.2.0/255.255.0.0
ALL : 127.0.0.0/255.0.0.0
--------------------------------------
IMPORTANT: At the end of this laboratory class, allow [tcpd] access to
all services on your host, from all. Enter a single line
ALL : ALL
in the file [/etc/hosts.allow].
------------------
Manuals of telnetd(8),telnet(1),issue.net(5),tcpd(8)
and hosts_access(5).
Square brackets are used to separate keywords, such as filenames,
programs names etc etc from lines of text. They have no other meaning.
A TELNET server, with minimal configuration, is to be used in this
experiment.
Create a directory named [telnet], in your home directory.
$ cd <-- puts you in your [home] directory
$ mkdir telnet
$ cd telnet
Installations are to be carried out from this directory. Binary
packages are to be installed. It is also possible to compile from
source code. Such source code may be down-loaded from Internet.
This experiment is to be carried out in Debian Linux platform. Some
Debian specific commands such as [dpkg], [dselect] etc etc have to be
used for software installation and removal. Other distributions have
similar commands of their own. Redhat Linux used [rpm] command.
The following command lists the softwares installed in your host.
$ dpkg -l
The output may be examined one screen at time
$ dpkg -l | more
If the name of the software is known partially it may be checked
$ dpkg -l | grep pyth
Find out the [telnet] related softwares installed in your host
$ dpkg -l | grep telnet
Typical output might be:
ii telnet 0.17-18woody2 The telnet client.
ii telnetd 0.17-18woody2 The telnet server.
The above lines indicate that [telnet] client and [telnet] servers are
installed in your host.
The status of the installed software can be checked.
Check the status of [telnet] client program. Output is not shown.
$ dpkg --status telnet
Check the status of [ telnetd ]. This is the server program. Output is
not shown.
$ dpkg --status telnetd
Test [telnetd] and [telnet] programs in your host
$ telnet 127.0.0.1
You may login in any user account if password is known.
As this experiment is on installation, the installed packages are to
be removed and then reinstalled.
Note: Installation and removal of software needs [root] privilege.
Remove the TELNET client program [telnet]
# dpkg -r telnet
Now the following command should fail
$ telnet 127.0.0.1
Check the [telnet] related installed packages.
$ dpkg -l | grep telnet
Output might be:
rc telnet 0.17-18woody2 The telnet client.
ii telnetd 0.17-18woody2 The telnet server.
The [ telnet ] program was removed but its configuration file was not
removed. Remove the configuration file.
# dpkg --purge telnet
Check the [telnet] related installed packages.
$ dpkg -l | grep telnet
Output might be:
ii telnetd 0.17-18woody2 The telnet server.
Check the status of [telnet] client program. Output is not shown.
$ dpkg --status telnet
Remove TELNET server program with its configuration file/files.
# dpkg --purge telnetd
Check the [telnet] related installed packages.
$ dpkg -l | grep telnet
Copy [ telnet ] and [ telnetd ] binary packages in your [ telnet ]
directory. You may use NFS or FTP for copying.
The package names might be
telnet_0.17-18woody2_i386.deb
and telnetd_0.17-18woody2_i386.deb
Note: The files are also available in first CD of a set of seven CDs.
These CDs are kept in the laboratory.
Install the TELNET client program
# dpkg -i telnet_0.17-18woody2_i386.deb
Check status of [telnet]
$ dpkg --status telnet
At present the TELNET client program is installed. Next command should
fail, as there is no TELNET server running on this host
$ telnet 127.0.0.1
However the client program can be used to access TELNET server running
on other host. Replace 192.16.5.251 with a suitable address.
$ telnet 192.16.5.251
Install the TELNET server program
# dpkg -i telnetd_0.17-18woody2_i386.deb
Check status of [telnetd]
$ dpkg --status telnetd
Find out where the executable(binary) of [telnetd] is installed
$ whereis -b in.telnetd
Location of [in.telnetd] -->
Briefly read manual of the TELNET server
$ man 8 telnetd
From the manual we find that the file [/etc/issue.net] is a text file
which contains a message or system identification to be printed before
the login prompt of a [telnet] session.
To know about the syntax of the file [ /etc/issue.net ], its manual is
consulted.
$ man 5 issue.net
A new [ issue.net ] is to be prepared, to provide the following to a
[telnet] client:
Welcome message
System node name (FQDN)
Current time and date
Name of the operating system and OS release name
Machine (hardware) type
Before modification, the original file is saved with a distinctive
extension for later identification.
$ cp /etc/issue.net ./issue.net-$USER-$( /bin/date +%H-%M )
Note the name of the saved file
$ ls -l | grep issue
Name of saved file-->
Edit [/etc/issue.net]
# nano /etc/issue.net
The file should contain the following text. Replace Sumit with your
name.
-------- /etc/issue.net --------
Welcome to Sumit's TELNET server
Terminal -----> %t
Server name --> %h
Date & time --> %d
OS -----------> %s %r
Hardware -----> %m
--------------------------------
Save the file.
Request two of your friends to [telnet] to your host. 192.169.5.146 is
assumed to be your IP address.
friend1 $ telnet 192.169.5.146
friend2 $ telnet 192.169.5.146
They should get the above information.
A server program may be kept running on a host. Such servers are
called stand-alone servers. Frequently used servers, such as [ named ]
( name server ), [ exim ] ( mail server ) run as stand-alone servers.
Less frequently used servers such as [ date ], [ echo ] etc etc do not
run always. A master server called [inetd] runs always. When a request
for a less frequently used server such as [date] comes, [inetd] starts
the [ date ] server. Usually [ telnetd ] is started by [inetd].
Note: [ date ], [ echo ] are two of the trivial services provided
internally by [ inetd ].
Note: [ xinetd ] is another master server with more functionality than
[ inetd ].
Examine file [ /etc/inetd.conf ] to find out if [ telnetd ] is started
by [inetd].
$ less /etc/inetd.conf
Was there any entry for [telnet] service ( Y / N )
A typical entry for [telnet] service is shown
telnet stream tcp nowait telnetd.telnetd /usr/sbin/tcpd /usr/sbin/in.telnetd
Note: The entry must be on a SINGLE line. A comment ( hash ) before a
service name, disables the service.
The [telnetd] is to be disabled using file [ /etc/inetd.conf ]
Edit file [ /etc/inetd.conf ]
# nano /etc/inetd.conf
Put a hash ( # ) mark before [telnet] service name and save the file.
Try to [telnet] to localhost.
$ telnet 127.0.0.1
This should succeed in spite of the hash before the service name. The
[inetd] process is not yet aware of the modifications made by you. If
SIGHUP signal is delivered to [ inetd ] process, its signal handler
makes arrangement to re-read its configuration file. [/etc/inetd.conf]
is the configuration file of [inetd] process.
Find out PID of [inetd] daemon process
$ ps ax | grep inetd
PID-of-inetd-->
Send SIGHUP signal to [ inetd ] daemon, to re-read [ /etc/inetd.conf ]
# kill -SIGHUP pid-of-inetd
Try to [telnet] to localhost. Now it should fail
$ telnet 127.0.0.1
Describe the steps to enable TELNET service.
Again examine the following line from [ /etc/inetd.conf ] file.
telnet stream tcp nowait telnetd.telnetd /usr/sbin/tcpd /usr/sbin/in.telnetd
The field [ /usr/sbin/tcpd ] indicates that access to [telnet] service
is controlled by [tcpd].
Access control to your host with [tcpd]:
[tcpd] program can be used to
control access to some of the services offered by your host, with two
files:
[ /etc/hosts.allow ] and [ /etc/hosts.deny ]
For access control to be effective, [tcpd] must be called first to get
the service. Check file [ /etc/inetd.conf ] to find out the services
controlled by [tcpd]. You may read manual of [tcpd(8)].
The access control software consults [/etc/hosts.allow] first and then
[/etc/hosts.deny]. The search stops at the first match. If no match is
found in either of the files, access is granted. To know about access
control rules you may read manual [hosts_access(5)].
Note: If extended access control rules are used, it is possible to use
a single access control file such as [/etc/hosts.allow].
You may read manual of hosts_options(5).
Case-1: Access is open:
The two files [/etc/hosts.allow] and
[/etc/hosts.deny] may be absent or may be present without any
rule.
OR
If the line:
ALL : ALL
is entered in [/etc/hosts.allow]. File [/etc/hosts.deny] would
not be consulted in this case, as file [ /etc/hosts.allow ] is
checked first.
Case-2: Access is mostly open and access is denied on specific cases.
File [/etc/hosts.allow] may be absent or empty of rules. File
[/etc/hosts.deny] blocks access specifically.
Example:
Edit the file [/etc/hosts.deny]
# nano /etc/hosts.deny
Add the following line in that file
in.telnetd : sumit@127.0.0.1
Save the file.
The above line deny access to user [sumit] to [telnet]
service from host 127.0.0.1 ( localhost ).
Login as [sumit] and [telnet] to localhost
sumit $ telnet 127.0.0.1
Was it successful ? ( y / N )
Login as [you] and [telnet] to localhost
you $ telnet 127.0.0.1
Was it successful ? ( Y / n )
Case-3: Access is mostly closed and access is granted on specific
cases.
Note: Paranoid System Administrators might use this scheme
The file [/etc/hosts.deny] contains a single line
ALL : ALL
This line denies access to all. As [ /etc/hosts.allow ] is
checked first, specific cases are granted access in that file.
Example:
Edit the file [/etc/hosts.deny] and add a single line
All : ALL
Save the file.
Edit [/etc/hosts.allow] and keep it blank.
Try to [telnet] to localhost as [sumit], [you],[guest]
or any other user
Were these successful ? ( y / N )
Edit [/etc/hosts.allow] and add the following line in
that file
in.telnetd : sumit@127.0.0.1
Save the file.
Try to [telnet] to localhost as [sumit]
sumit $ telnet 127.0.0.1
Was it successful ? ( Y / n )
Try to [telnet] to localhost as [you], [guest] or any
user other than [sumit]
Were these successful ? ( y / N )
Assignment-1:
Configure your host as a mostly closed system using
[tcpd] and allow:
a. [telnet] access from 172.16.2.0 network.
b. Access to all services from localhost (127.0.0.1)
Enter suitable entries in the two files
------- /etc/hosts.allow ---------
----------------------------------
--- /etc/hosts.deny ---
ALL : ALL
-----------------------
The following steps were followed to install TELNET server
1. The binary package of [telnetd] was installed
# dpkg -i telnetd_0.17-18woody2_i386.deb
2. The file [/etc/issue.net] was modified to provide some information
to the [telnet] clients.
3.
(a) Hash before [ telnet ] service line in [ /etc/inetd ] file was
removed.
(b) PID of [inetd] super-server was determined.
(c) SIGHUP signal was sent to [inetd] daemon process.
4. Mostly closed [tcpd] access control was imposed.
(a) ALL : ALL was entered in [/etc/hosts.allow] file.
(b) The file [/etc/hosts.allow] was modified as under
--------------------------------------
in.telnetd : 172.16.2.0/255.255.0.0
ALL : 127.0.0.0/255.0.0.0
--------------------------------------
IMPORTANT: At the end of this laboratory class, allow [tcpd] access to
all services on your host, from all. Enter a single line
ALL : ALL
in the file [/etc/hosts.allow].
------------------
Socket 2
Documents to read:
1. Internetworking with TCP/IP Volume-III
by
Douglas E. Comer & David L. Stevens
2. Manuals socket(2), ip(7),
tcp(7) and fork(2)
Square brackets are used to separate keywords, such as filenames,
programs names etc etc from lines of text. They have no other meaning.
Create directory [socket2] in your home directory.
$ mkdir $HOME/socket2
Change into [socket2] directory
$ cd $HOME/socket2
Bring the file [ socket2-681.txt ] in this directory using NFS or FTP.
Creation of a new process:
A new process can be created with [fork()]
system call. Read manual of fork.
$ man 2 fork
After the [fork()] call, the newly created process is called [ child ]
and the main program is called [parent] process. The codes that follow
the [fork()] call is executed by the [ parent ] and the [ child ]. Who
executes first is not predictable.
Save the following code as [f1.c].
--------------------------------------------------
// file-name f1.c
// example of fork()
#include
#include
int main( void)
{
pid_t x;
// a new process is created
x = fork();
// following lines are executed by two processes
write( STDOUT_FILENO,"My name is Sumit\n", 17 );
return 0;
}
--------------------------------------------------
Compile and execute the program.
$ gcc -Wall ./f1.c -o ./one
$ ./one
Was the line "My name is Sumit" printed twice ? ( Y / n )
The two processes can be made to execute separate blocks of code. The
[ fork() ] call returns two PID values. The variable [ x ] gets two
values. The [child] gets x=0 and the parent gets x=some-other-integer.
Zero is not the PID of the [ child ] process, but this can be used to
confine the [child] process to a given block of code. The rest of the
codes are executed by the parent process.
Save the following as [f2.c]
----------------------------------------------------
// file-name f2.c
// example of fork()
#include
#include
#include
int main( void)
{
pid_t x;
x = fork();
// two values of x are printed.
printf("x = %u\n", x );
// both the processes sleep for a second. This is
// used only to impart some clarity in the output.
sleep(1);
if( x == 0 ) // child process
{
printf("x = %u; I am child\n", x );
exit(0);
} // end of child's block
// rest is parent process
printf("x = %u; I am parent\n", x );
return 0;
}
----------------------------------------------------
Compile and run the program.
$ gcc -Wall ./f2.c -o ./two
$ ./two
Did the child execute it's block of code ? ( Y / n )
Run the program a number of times.
Was the parent running first ? ( y / n / unpredictable )
In a concurrent server using process, a new [child] process is created
for each client's request. While a client's request is being processed
by the [ child ] process, the parent waits for the next request from
another client. If the [child] exits but the parent continues and does
not read the exit status of the child; [ zombie ] process is created.
The next program creates ten [zombie] processes.
Save the following program as [f3.c]
---------------------------------
// file-name f3.c
// creation of zombie process
#include
#include
#include
#include
int main( void)
{
pid_t x;
int n = 10;
while( n > 0 )
{
x = fork();
if( x == 0 ) // child process
{
exit(0);
} // end of child's block
n--;
//wait(NULL);
}
while(1) { sleep(1); }
}
---------------------------------
Compile and run the executable.
$ gcc -Wall ./f3.c -o ./three
$ ./three
In another terminal check processes
$ ps ax
Were zombies created ? ( Y / n )
When the parent exits, the operating system removes the zombies.
Terminate [three] with CTRL-c.
Were zombies removed ? ( Y / n )
The [zombie] processes, if not reaped (removed), use system resources.
If the [parent] reads the exit status of a [child], the [ zombie ] is
removed. Parent can use [ wait() ] system call to read the exit status
of a child. You may read the manual of [wait] and [waitpid] calls.
$ man 2 wait
Uncomment the line
//wait(NULL);
in [f3.c], compile and run the executable.
$ gcc -Wall ./f3.c -o ./three
$ ./three
In another terminal check the processes
$ ps ax
Was any zombie created ? ( y / N )
Terminate [three] with CTRL-c.
Whenever a [ child ] exits or stops, the operating system delivers a
SIGCHLD signal to the [parent] process. In [f4.c], the parent installs
a signal handler for SIGCHLD. The [parent] reads the exit status of a
child within the signal handler, whenever a [ child ] stops or exits.
The SIGCHLD signal might interrupt whatever the parent was executing.
The program [f4.c] is a concurrent TCP ECHO server. This program uses
a SIGCHLD handler to reap zombies.
------------------------------------------------------------
// file-name f4.c
// TCP ECHO server( concurrent - using process )
// Using SIGCHLD handler to reap zombie
// usage: program-name
#include
#include
#include
#include
#include
#include
#include
#include
#define LOCAL_PORT 65432
// signal handler prototype
void reap_zombie( int signum );
// a global variable
jmp_buf yy;
int main ( void )
{
int serv_sd; // socket descriptor
int temp_sd; // socket descriptor
int n;
struct sockaddr_in serv_addr; // IPv4 address
struct sigaction act; // signal action
sigset_t ss; // signal set
pid_t pid;
// members of [serv_addr] are initialised
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons( LOCAL_PORT );
serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );
// TCP ( IPv4 stream ) socket is created
serv_sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( serv_sd == -1 ) { perror("socket-call"); exit(1); }
// TCP socket is bound to a local address
n = bind( serv_sd,
( struct sockaddr *) &serv_addr,
sizeof(serv_addr) );
if( n == -1 ) { perror("bind-call"); exit(1); }
// TCP socket is put in listening state
n = listen( serv_sd, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// main installs signal handler for SIGCHLD
act.sa_handler = reap_zombie;
act.sa_mask = ss;
act.sa_flags = 0;
n = sigaction( SIGCHLD, &act, NULL );
if ( n == -1 ) { perror("sigaction"); exit(1); }
// server accepts client's request in an endless loop
while( 1 )
{
printf( "accepting request on TCP port %u\n",
LOCAL_PORT );
// If [accept()] call is interrupted by SIGCHLD, return
// here from signal handler.
n = sigsetjmp(yy,1); // second argument is non-zero
if( n == 0 ) printf("normal flow\n");
if( n == 66 ) printf("returning from interrupt\n");
temp_sd = accept( serv_sd, NULL, 0 );
if( temp_sd == -1 ) perror("accept-call");
pid = fork();
if( pid == -1 ) perror("fork");
if( pid == 0 ) // child process handles client's request
{
#define BUFFERSIZE 1024
char buffer[BUFFERSIZE];
ssize_t i, j ;
// clear buffer
memset( buffer, '\0', BUFFERSIZE );
// read clients request string in the buffer
i = read( temp_sd, buffer, BUFFERSIZE );
printf("child: %u bytes received from client\n", i );
// write the contents of the buffer in the [temp_sd]
j = write( temp_sd, buffer, i );
if( j == -1 ) { perror("write-call"); }
shutdown( temp_sd, SHUT_RDWR );
close( temp_sd );
exit(0);
} // end of child's block
// rest is parent's code
close( temp_sd );
} //end of endless loop
return 0;
} //end of main
// signal handler
void reap_zombie( int signum )
{
pid_t pid;
printf("reap-zombie: received signal %u\n", signum );
pid = waitpid( 0, NULL, WNOHANG );
if( pid == -1 ) perror("waitpid");
siglongjmp(yy,66);
}
------------------------------------------------------------
Compile and run the server.
$ gcc -Wall ./f4.c -o ./four
$ ./four
Request your friends to use your ECHO server.
friend $ tcp-echo-client your-ip-address your-port-number
From another terminal use your ECHO server repeatedly.
$ tcp-echo-client 127.0.0.1 65432
Check processes
$ ps ax
Was there any zombie process ? ( y / N )
If reaping of [ zombie ] is not done with SIGCHLD handler, the above
program can be simplified. In [f5.c] SIGCHLD handler is not used.
-------------------------------------------------------------------
// file-name f5.c
// TCP ECHO server(concurrent - using fork) without SIGCHLD handler
// usage: program-name
#include
#include
#include
#include
#include
#include
#define LOCAL_PORT 65432
int main ( void )
{
int serv_sd; // socket descriptor
int temp_sd; // socket descriptor
int n;
struct sockaddr_in serv_addr; // IPv4 address
pid_t pid,x;
// members of [serv_addr] are initialised
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons( LOCAL_PORT );
serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );
// TCP ( IPv4 stream ) socket is created
serv_sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( serv_sd == -1 ) { perror("socket-call"); exit(1); }
// TCP socket is bound to a local address
n = bind( serv_sd,
( struct sockaddr *) &serv_addr,
sizeof(serv_addr) );
if( n == -1 ) { perror("bind-call"); exit(1); }
// TCP socket is put in listening state
n = listen( serv_sd, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// server accepts client's request in an endless loop
while( 1 )
{
printf( "server: accepting request on TCP port %u\n",
LOCAL_PORT );
temp_sd = accept( serv_sd, NULL, 0 );
if( temp_sd == -1 ) perror("accept-call");
// create a process
pid = fork();
if( pid == -1 ) { perror("fork"); exit(1); }
if( pid == 0 ) // child process handles client's request
{
#define BUFFERSIZE 1024
char buffer[BUFFERSIZE];
ssize_t i, j ;
// clear buffer
memset( buffer, '\0', BUFFERSIZE );
// read clients request string in the buffer
i = read( temp_sd, buffer, BUFFERSIZE );
printf("server: %u bytes received from client\n", i );
// write the contents of the buffer in the [temp_sd]
j = write( temp_sd, buffer, i );
if( j == -1 ) { perror("write-call"); }
shutdown( temp_sd, SHUT_RDWR );
close( temp_sd );
exit(0);
} // end of child's block
// rest is parent's code
close( temp_sd );
x = waitpid( 0, NULL, WNOHANG );
if( x == -1 ) perror("waitpid");
} //end of endless loop
return 0;
} //end of main
-------------------------------------------------------------------
Compile and run the server
$ gcc -Wall ./f5.c -o ./ser-con-p
$ ./ser-con-p
Use the ECHO server repeatedly
$ tcp-echo-client 127.0.0.1 65432
Was some zombie remained in system ? ( Y / n )
In the following program [f6.c], main program creates a [ thread ] to
process a client's request, after a successful [accept()] system call.
When a [ thread ] is created, it starts to execute it's start routine,
with the supplied argument. Main program creates the [thread] with the
newly created socket, as the argument.
----------------------------------------------------------------------
// file-name f6.c
// TCP echo server (concurrent - using threads)
// usage: program-name
#include
#include
#include
#include
#include
#define PORT 65432
void func( int arg );
int main(void)
{
int ser_sd,tempsd;
int n;
struct sockaddr_in ser_addr;
pthread_t x; // a thread item
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons( PORT );
ser_addr.sin_addr.s_addr = htonl( INADDR_ANY );
ser_sd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( ser_sd == -1 ) { perror("socket"); exit(1); }
n = bind( ser_sd,(struct sockaddr *) &ser_addr,
sizeof(ser_addr) );
if( n == -1) { perror("bind"); exit(1); }
n = listen( ser_sd, 5 );
if( n == -1 ) { perror("listen"); exit(1); }
while ( 1 )
{
printf("server is ready on TCP port %u \n", PORT );
// wait for a client's request
tempsd = accept( ser_sd, NULL, 0 );
if( tempsd == -1 ) perror("accept");
else
{
printf("creating a thread to process client's request\n");
n = pthread_create( &x, NULL,( void *) func, (void *) tempsd );
if( n != 0 ) perror("pthread_create");
}
} // endless loop
return 0;
}
// client's request is processes by this thread
void func( int arg )
{
#define BUFFERSIZE 1024
char buffer[BUFFERSIZE];
ssize_t i,j;
int n;
memset(buffer, '\0', BUFFERSIZE);
i = read( arg, buffer, BUFFERSIZE);
if( i == -1 ) { perror("read"); exit(1); }
printf("thread: read %u bytes from server\n", i );
// write [i] bytes to client
j = write( arg, buffer, i );
if(j == -1 ) { perror("write"); exit(1); }
n = shutdown( arg, SHUT_RDWR );
if( n == -1 ) { perror("shutdown"); }
close(arg);
pthread_exit(NULL);
}
----------------------------------------------------------------------
Compile and run the executable.
$ gcc -Wall -D_RENTRANT -lpthread ./f6.c -o ./ser-con-t
$ ./ser-con-t
Test the ECHO server from localhost and from other hosts.
Did the ECHO server process multiple client requests ? ( Y / n )
----------------------------
Optional assignment-1:
Trace system calls and signals when the program
[four] executes and client connects to it.
$ strace ./four
Optional assignment-2:
Capture packets generated by client and server.
Start ECHO server
$ ./ser-con-t
In another terminal, capture TCP packets, to and from your host. Save
the captured packets in a file [kk] in the current directory.
# tcpdump -i eth0 host your-ip-address and tcp -w ./kk
The data in file [ kk ] is not text. Convert the captured data into
text and save it in file [jj]. in the current directory.
# tethereal -V -r ./kk > ./jj
Examine the text file.
# less ./jj
-------------------
1. Internetworking with TCP/IP Volume-III
by
Douglas E. Comer & David L. Stevens
2. Manuals socket(2), ip(7),
tcp(7) and fork(2)
Square brackets are used to separate keywords, such as filenames,
programs names etc etc from lines of text. They have no other meaning.
Create directory [socket2] in your home directory.
$ mkdir $HOME/socket2
Change into [socket2] directory
$ cd $HOME/socket2
Bring the file [ socket2-681.txt ] in this directory using NFS or FTP.
Creation of a new process:
A new process can be created with [fork()]
system call. Read manual of fork.
$ man 2 fork
After the [fork()] call, the newly created process is called [ child ]
and the main program is called [parent] process. The codes that follow
the [fork()] call is executed by the [ parent ] and the [ child ]. Who
executes first is not predictable.
Save the following code as [f1.c].
--------------------------------------------------
// file-name f1.c
// example of fork()
#include
#include
int main( void)
{
pid_t x;
// a new process is created
x = fork();
// following lines are executed by two processes
write( STDOUT_FILENO,"My name is Sumit\n", 17 );
return 0;
}
--------------------------------------------------
Compile and execute the program.
$ gcc -Wall ./f1.c -o ./one
$ ./one
Was the line "My name is Sumit" printed twice ? ( Y / n )
The two processes can be made to execute separate blocks of code. The
[ fork() ] call returns two PID values. The variable [ x ] gets two
values. The [child] gets x=0 and the parent gets x=some-other-integer.
Zero is not the PID of the [ child ] process, but this can be used to
confine the [child] process to a given block of code. The rest of the
codes are executed by the parent process.
Save the following as [f2.c]
----------------------------------------------------
// file-name f2.c
// example of fork()
#include
#include
#include
int main( void)
{
pid_t x;
x = fork();
// two values of x are printed.
printf("x = %u\n", x );
// both the processes sleep for a second. This is
// used only to impart some clarity in the output.
sleep(1);
if( x == 0 ) // child process
{
printf("x = %u; I am child\n", x );
exit(0);
} // end of child's block
// rest is parent process
printf("x = %u; I am parent\n", x );
return 0;
}
----------------------------------------------------
Compile and run the program.
$ gcc -Wall ./f2.c -o ./two
$ ./two
Did the child execute it's block of code ? ( Y / n )
Run the program a number of times.
Was the parent running first ? ( y / n / unpredictable )
In a concurrent server using process, a new [child] process is created
for each client's request. While a client's request is being processed
by the [ child ] process, the parent waits for the next request from
another client. If the [child] exits but the parent continues and does
not read the exit status of the child; [ zombie ] process is created.
The next program creates ten [zombie] processes.
Save the following program as [f3.c]
---------------------------------
// file-name f3.c
// creation of zombie process
#include
#include
#include
#include
int main( void)
{
pid_t x;
int n = 10;
while( n > 0 )
{
x = fork();
if( x == 0 ) // child process
{
exit(0);
} // end of child's block
n--;
//wait(NULL);
}
while(1) { sleep(1); }
}
---------------------------------
Compile and run the executable.
$ gcc -Wall ./f3.c -o ./three
$ ./three
In another terminal check processes
$ ps ax
Were zombies created ? ( Y / n )
When the parent exits, the operating system removes the zombies.
Terminate [three] with CTRL-c.
Were zombies removed ? ( Y / n )
The [zombie] processes, if not reaped (removed), use system resources.
If the [parent] reads the exit status of a [child], the [ zombie ] is
removed. Parent can use [ wait() ] system call to read the exit status
of a child. You may read the manual of [wait] and [waitpid] calls.
$ man 2 wait
Uncomment the line
//wait(NULL);
in [f3.c], compile and run the executable.
$ gcc -Wall ./f3.c -o ./three
$ ./three
In another terminal check the processes
$ ps ax
Was any zombie created ? ( y / N )
Terminate [three] with CTRL-c.
Whenever a [ child ] exits or stops, the operating system delivers a
SIGCHLD signal to the [parent] process. In [f4.c], the parent installs
a signal handler for SIGCHLD. The [parent] reads the exit status of a
child within the signal handler, whenever a [ child ] stops or exits.
The SIGCHLD signal might interrupt whatever the parent was executing.
The program [f4.c] is a concurrent TCP ECHO server. This program uses
a SIGCHLD handler to reap zombies.
------------------------------------------------------------
// file-name f4.c
// TCP ECHO server( concurrent - using process )
// Using SIGCHLD handler to reap zombie
// usage: program-name
#include
#include
#include
#include
#include
#include
#include
#include
#define LOCAL_PORT 65432
// signal handler prototype
void reap_zombie( int signum );
// a global variable
jmp_buf yy;
int main ( void )
{
int serv_sd; // socket descriptor
int temp_sd; // socket descriptor
int n;
struct sockaddr_in serv_addr; // IPv4 address
struct sigaction act; // signal action
sigset_t ss; // signal set
pid_t pid;
// members of [serv_addr] are initialised
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons( LOCAL_PORT );
serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );
// TCP ( IPv4 stream ) socket is created
serv_sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( serv_sd == -1 ) { perror("socket-call"); exit(1); }
// TCP socket is bound to a local address
n = bind( serv_sd,
( struct sockaddr *) &serv_addr,
sizeof(serv_addr) );
if( n == -1 ) { perror("bind-call"); exit(1); }
// TCP socket is put in listening state
n = listen( serv_sd, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// main installs signal handler for SIGCHLD
act.sa_handler = reap_zombie;
act.sa_mask = ss;
act.sa_flags = 0;
n = sigaction( SIGCHLD, &act, NULL );
if ( n == -1 ) { perror("sigaction"); exit(1); }
// server accepts client's request in an endless loop
while( 1 )
{
printf( "accepting request on TCP port %u\n",
LOCAL_PORT );
// If [accept()] call is interrupted by SIGCHLD, return
// here from signal handler.
n = sigsetjmp(yy,1); // second argument is non-zero
if( n == 0 ) printf("normal flow\n");
if( n == 66 ) printf("returning from interrupt\n");
temp_sd = accept( serv_sd, NULL, 0 );
if( temp_sd == -1 ) perror("accept-call");
pid = fork();
if( pid == -1 ) perror("fork");
if( pid == 0 ) // child process handles client's request
{
#define BUFFERSIZE 1024
char buffer[BUFFERSIZE];
ssize_t i, j ;
// clear buffer
memset( buffer, '\0', BUFFERSIZE );
// read clients request string in the buffer
i = read( temp_sd, buffer, BUFFERSIZE );
printf("child: %u bytes received from client\n", i );
// write the contents of the buffer in the [temp_sd]
j = write( temp_sd, buffer, i );
if( j == -1 ) { perror("write-call"); }
shutdown( temp_sd, SHUT_RDWR );
close( temp_sd );
exit(0);
} // end of child's block
// rest is parent's code
close( temp_sd );
} //end of endless loop
return 0;
} //end of main
// signal handler
void reap_zombie( int signum )
{
pid_t pid;
printf("reap-zombie: received signal %u\n", signum );
pid = waitpid( 0, NULL, WNOHANG );
if( pid == -1 ) perror("waitpid");
siglongjmp(yy,66);
}
------------------------------------------------------------
Compile and run the server.
$ gcc -Wall ./f4.c -o ./four
$ ./four
Request your friends to use your ECHO server.
friend $ tcp-echo-client your-ip-address your-port-number
From another terminal use your ECHO server repeatedly.
$ tcp-echo-client 127.0.0.1 65432
Check processes
$ ps ax
Was there any zombie process ? ( y / N )
If reaping of [ zombie ] is not done with SIGCHLD handler, the above
program can be simplified. In [f5.c] SIGCHLD handler is not used.
-------------------------------------------------------------------
// file-name f5.c
// TCP ECHO server(concurrent - using fork) without SIGCHLD handler
// usage: program-name
#include
#include
#include
#include
#include
#include
#define LOCAL_PORT 65432
int main ( void )
{
int serv_sd; // socket descriptor
int temp_sd; // socket descriptor
int n;
struct sockaddr_in serv_addr; // IPv4 address
pid_t pid,x;
// members of [serv_addr] are initialised
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons( LOCAL_PORT );
serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );
// TCP ( IPv4 stream ) socket is created
serv_sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( serv_sd == -1 ) { perror("socket-call"); exit(1); }
// TCP socket is bound to a local address
n = bind( serv_sd,
( struct sockaddr *) &serv_addr,
sizeof(serv_addr) );
if( n == -1 ) { perror("bind-call"); exit(1); }
// TCP socket is put in listening state
n = listen( serv_sd, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// server accepts client's request in an endless loop
while( 1 )
{
printf( "server: accepting request on TCP port %u\n",
LOCAL_PORT );
temp_sd = accept( serv_sd, NULL, 0 );
if( temp_sd == -1 ) perror("accept-call");
// create a process
pid = fork();
if( pid == -1 ) { perror("fork"); exit(1); }
if( pid == 0 ) // child process handles client's request
{
#define BUFFERSIZE 1024
char buffer[BUFFERSIZE];
ssize_t i, j ;
// clear buffer
memset( buffer, '\0', BUFFERSIZE );
// read clients request string in the buffer
i = read( temp_sd, buffer, BUFFERSIZE );
printf("server: %u bytes received from client\n", i );
// write the contents of the buffer in the [temp_sd]
j = write( temp_sd, buffer, i );
if( j == -1 ) { perror("write-call"); }
shutdown( temp_sd, SHUT_RDWR );
close( temp_sd );
exit(0);
} // end of child's block
// rest is parent's code
close( temp_sd );
x = waitpid( 0, NULL, WNOHANG );
if( x == -1 ) perror("waitpid");
} //end of endless loop
return 0;
} //end of main
-------------------------------------------------------------------
Compile and run the server
$ gcc -Wall ./f5.c -o ./ser-con-p
$ ./ser-con-p
Use the ECHO server repeatedly
$ tcp-echo-client 127.0.0.1 65432
Was some zombie remained in system ? ( Y / n )
In the following program [f6.c], main program creates a [ thread ] to
process a client's request, after a successful [accept()] system call.
When a [ thread ] is created, it starts to execute it's start routine,
with the supplied argument. Main program creates the [thread] with the
newly created socket, as the argument.
----------------------------------------------------------------------
// file-name f6.c
// TCP echo server (concurrent - using threads)
// usage: program-name
#include
#include
#include
#include
#include
#define PORT 65432
void func( int arg );
int main(void)
{
int ser_sd,tempsd;
int n;
struct sockaddr_in ser_addr;
pthread_t x; // a thread item
ser_addr.sin_family = AF_INET;
ser_addr.sin_port = htons( PORT );
ser_addr.sin_addr.s_addr = htonl( INADDR_ANY );
ser_sd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if( ser_sd == -1 ) { perror("socket"); exit(1); }
n = bind( ser_sd,(struct sockaddr *) &ser_addr,
sizeof(ser_addr) );
if( n == -1) { perror("bind"); exit(1); }
n = listen( ser_sd, 5 );
if( n == -1 ) { perror("listen"); exit(1); }
while ( 1 )
{
printf("server is ready on TCP port %u \n", PORT );
// wait for a client's request
tempsd = accept( ser_sd, NULL, 0 );
if( tempsd == -1 ) perror("accept");
else
{
printf("creating a thread to process client's request\n");
n = pthread_create( &x, NULL,( void *) func, (void *) tempsd );
if( n != 0 ) perror("pthread_create");
}
} // endless loop
return 0;
}
// client's request is processes by this thread
void func( int arg )
{
#define BUFFERSIZE 1024
char buffer[BUFFERSIZE];
ssize_t i,j;
int n;
memset(buffer, '\0', BUFFERSIZE);
i = read( arg, buffer, BUFFERSIZE);
if( i == -1 ) { perror("read"); exit(1); }
printf("thread: read %u bytes from server\n", i );
// write [i] bytes to client
j = write( arg, buffer, i );
if(j == -1 ) { perror("write"); exit(1); }
n = shutdown( arg, SHUT_RDWR );
if( n == -1 ) { perror("shutdown"); }
close(arg);
pthread_exit(NULL);
}
----------------------------------------------------------------------
Compile and run the executable.
$ gcc -Wall -D_RENTRANT -lpthread ./f6.c -o ./ser-con-t
$ ./ser-con-t
Test the ECHO server from localhost and from other hosts.
Did the ECHO server process multiple client requests ? ( Y / n )
----------------------------
Optional assignment-1:
Trace system calls and signals when the program
[four] executes and client connects to it.
$ strace ./four
Optional assignment-2:
Capture packets generated by client and server.
Start ECHO server
$ ./ser-con-t
In another terminal, capture TCP packets, to and from your host. Save
the captured packets in a file [kk] in the current directory.
# tcpdump -i eth0 host your-ip-address and tcp -w ./kk
The data in file [ kk ] is not text. Convert the captured data into
text and save it in file [jj]. in the current directory.
# tethereal -V -r ./kk > ./jj
Examine the text file.
# less ./jj
-------------------
Socket1
Documents to read:
1. UNIX Network Programming
By W. Richard Stevens
Chapter-6, on Berkeley Sockets
2. Manuals socket(2), ip(7),
tcp(7) and udp(7)
Square brackets are used to separate keywords, such as filenames,
programs names etc etc from lines of text. They have no other meaning.
Go to your home directory
$ cd
Verify the current directory
$ pwd
Create directory [socket1] in your home directory.
$ mkdir socket1
Change into [socket1] directory
$ cd socket1
Bring the file [socket1.txt] in this directory using NFS
$ mount /ftp-server
$ cd /ftp-server
.
.
You may also use [ftp] to bring the file.
SOCKET:
A socket is an endpoint for communication. Sockets are the
primary means of communicating with other hosts; telnet, rlogin, ftp,
talk and the other familiar network programs use sockets.
Different types of [socket]s can be created by [socket()] system call.
Consult the manual of this system call from section 2 of manual.
$ man 2 socket
[socket()] call takes three arguments. An unsigned integer is returned
when the call is successful. This integer is the file descriptor of
the socket. As with regular file descriptors, writing in the socket,
reading from the socket, closing the socket etc etc can be done, using
this descriptor.
Type of the created socket depends on the arguments used. In this
laboratory, we are going to use sockets suitable for network communic-
ation using IPv4 Internet protocols. From the above manual we find
that we have to consult the manual of [ip] from section 7 of the UNIX
manual, for the arguments to be used for creating IPv4 sockets.
$ man 7 ip
A TCP socket ( IPv4 stream socket ) can be created with...
tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
An UDP socket ( IPv4 datagram socket ) can be created with...
udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
Zero may be used to replace IPPROTO_TCP and IPPROTO_UDP. Zero is IP
pseudo protocol number.
We are not going to use [raw_socket] in this experiment.
Save the following program as [f1.c].
---------------------------------------------------------------------
// file-name f1.c
// One TCP and one UDP socket are created
// usage: program-name
#include
#include
#include
#include
int main ( void )
{
int sd1, sd2 ;
// sd1 and sd2 would be used as socket-file-descriptors
// Values of two symbolic constants are printed
printf("IPPROTO_TCP = %u \n", IPPROTO_TCP );
printf("IPPROTO_UDP = %u \n", IPPROTO_UDP );
// process number of this program
printf("PID = %u \n", getpid() );
// TCP ( IPv4 stream ) socket is created
sd1 = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
// Numerical value of the socket descriptor is printed
printf("value of TCP socket descriptor = %u \n", sd1 );
// UDP ( IPv4 datagram ) socket is created
sd2 = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
// Numerical value of the socket descriptor is printed
printf("value of UDP socket descriptor = %u \n", sd2 );
// If the program exits, operating system closes (removes) the
// descriptors. The following endless loop is used for checking
// the creation of the two sockets.
while( 1 ) { sleep(1); }
return 0;
} //end of main
---------------------------------------------------------------------
Assignment-1:
Compile the program
$ gcc -Wall ./f1.c -o ./one
Run the executable program, do not terminate the program and record
the following from the output of the program:
$ ./one
IPPROTO_TCP = ___
IPPROTO_UDP = ___
PID = ________
value of TCP socket descriptor = ___
value of UDP socket descriptor = ___
As the program runs in this terminal, this terminal is unusable now.
Note: The program can be started in background also.
$ ./one &
If the program runs in the background, this terminal becomes
usable.
Verify the PID of your program
$ ps ax | grep one
In another terminal, examine the file [/etc/protocols] and record the
following
$ less /etc/protocols
protocols-name protocols-number
IP ------------> ___
TCP -----------> ___
UDP -----------> ___
Check the creation of the sockets with the following command
$ ls -l /proc/value-of-PID/fd
Were the two sockets created ? ( Y / n )
Terminate the running program [one] with CTRL-C.
End of Assignment-1.
5-tuple association for network communication may be stated as:
(protocol,local-address,local-process,foreign-address,foreign-process)
Assignment-2.
In this assignment, a 5-tuple association for network
communication is to be verified. The [echo] server process using TCP,
running in your friend's host, are the [ foreign-address ], [ foreign-
process ] and [ protocol ].
Examine file [/etc/services] and record:
$ less /etc/services
[echo] server, using TCP protocol, runs on port number ____ .
[foreign-process] is NOT the PID of the [echo] server process, but it
is the port number, the [echo] server process associates with. If the
[ echo ] server process is restarted, its PID would change but its
association with port number - 7 would be unaltered. This port number
is well-known to the [ client/clients ].
At present we do not have any TCP [echo] client program. Later in this
experiment we are going to write a TCP [echo] client program.
[telnet] is a [client] program used to connect to the [telnetd] server
program. [ telnet ] connects to port-23 of the specified host, if port
number is not specified. If port number is specified, [ telnet ]
connects to that port.
The two commands should give the same result
$ telnet 192.168.5.145
or
$ telnet 172.16.2.145 23
If port number is specified as 7, [ telnet ] program may be used to
communicate with the [echo] server. Replace 172.16.2.145 with the IP
address of your friend's host.
$ telnet 172.16.2.145 7
Enter any string. It should be echoed on your terminal.
[ telnet ] program used in your host, is the [ local-process ]. PID of
[telnet] process is NOT the [[local-process], it is the port number it
is associated with. This port number ( in the range 1024 - 65535 ) is
alloted to that instance of [telnet] process, by the operating system
and it is guaranteed to be free, no other process using TCP protocol
was using it. The port assigned to the [ client ] process is called
ephemeral ( short lived ) port. The PID and the ephemeral port might
change with each invocation of the [client] process.
----------- ----------------
| | | |
| Your host |_____________________| Friend's Host |
| client | | echo server(7) |
| | | |
----------- ----------------
Connect to the [ echo ] server of your friend but do not enter any
string. In this condition a TCP connection is established.
$ telnet 172.16.2.145 7
In another terminal, login in your account ( or login as [root] ) and
use the following command.
$ ps ax
PID of the [telnet] process -->
Use the following command...
$ netstat -atnp
You may read manual of this command [ $ man 8 netstat ].
The meaning of the options are reproduced from the manual:
a all
t TCP
n numeric output
p show PID and program name
If the output is more than one screenful, you can store the result in
a file and examine the file with a pager, such as [less].
$ netstat -atnp >tmp 2>&1
$ less ./tmp
Fill up the following table.
proto loc-add:loc-port for-add:for-port state PID/prog-name
tcp :7 ESTABLISHED
The above is the 5-tuple association.
End of Assignment-2.
The system calls used by the [server] and the [client] for connection
oriented protocol are shown below ( From "UNIX Network Programming" by
W.Richard Stevens ). TCP is a connection oriented protocol.
SERVER
socket()
|
bind()
|
listen()
|
accept() CLIENT
|
Blocks until connection socket()
from client |
| connection establishment |
|<-----------------------------------------> connect()
| |
read() <------------------------------------- write()
| data (request from client) |
| |
process client's request |
| |
write() --------------------------------------> read()
data (reply from server)
A newly created socket is not useful for communication. An address is
to be assigned to it.
The format of a IPv4 address is reproduces from manual [ip(7)].
struct sockaddr_in
{
sa_family_t sin_family; // address family: AF_INET
u_int16_t sin_port; // port in network byte
struct in_addr sin_addr; // internet address
};
// Internet address.
struct in_addr {
u_int32_t s_addr; // address in network byte order
};
Internet address and port number are to be in a format, called the
"network byte order".
When the members of a IPv4 address have been initialised, the newly
created socket is associated with this address, with [ bind ] system
call. [ bind ] call sets a local IP address and port number of the
socket. When it is needed to assign a specific port ( well-known) to a
socket, [bind] is used. Well-known ports are used by servers. [ bind ]
call is mainly used by servers.
[bind] call takes three arguments
int = bind( socket-descriptor,
address of local IPv4 address,
size of the IPv4 address in bytes )
You may read manual of bind(2)] for the exact syntax of the call.
[listen] system call makes a [socket] ready to accept incoming client
requests. [ listen ] call also sets a limit of the incoming connection
queue. [listen] call is valid for connection oriented protocols (TCP).
In the next program [f2.c] following are done:
One TCP and one UDP
socket are created. Members of the structure of one IPv4 address are
then initialised. This address is assigned to the UDP and TCP sockets.
Although the same IP address and port number are used, the two sockets
are bound to two different addresses, as two different protocols are
used. The TCP [socket] is put in listening state.
------------------------------------------------------------
// file-name f2.c
// bind() and listen() calls
// usage: program-name
#include
#include
#include
#include
#include
#define LOCAL_ADDRESS "127.0.0.1"
// 127.0.0.1 is the IP address of loopback interface
// Any free port ( 1024 to 65535 ) is chosen
#define LOCAL_PORT 65432
int main ( void )
{
int sd1, sd2 ;
int n;
struct sockaddr_in addr; // IPv4 address
// members of [addr] are initialised
addr.sin_family = AF_INET;
addr.sin_port = htons( LOCAL_PORT );
n = inet_aton( LOCAL_ADDRESS , &(addr.sin_addr) );
if( n == 0 )
{
printf("invalid-addr\n");
exit(1);
}
// TCP ( IPv4 stream ) socket is created
sd1 = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
// TCP socket is bound to a local address
n = bind( sd1, ( struct sockaddr *) &addr, sizeof(addr) );
if( n == -1 ) { perror("bind-call-1"); exit(1); }
// TCP socket is put in listening state
n = listen( sd1, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// UDP ( IPv4 datagram ) socket is created
sd2 = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
// UDP socket is bound to a local address
n = bind( sd2, ( struct sockaddr *) &addr, sizeof(addr) );
if( n == -1 ) { perror("bind-call-2"); exit(1); }
// endless loop
while( 1 ) { sleep(1); }
return 0;
} //end of main
---------------1---------------------------------------------
htons() function:
This function converts the short integer from host
byte order to network byte order. Port numbers are 16 bit long.
Read its manual.
$ man 3 htons
inet_aton() function:
This function converts the Internet host address
from the standard numbers-and-dots notation into binary data and
stores it in the address structure. This function returns nonzero if
the address is valid, zero if not.
Read its manual.
$ man 3 inet_aton
Assignment-3:
Compile and run the program.
$ gcc -Wall ./f2.c -o ./two-a
$ ./two-a
Use the following command and examine the output
$ netstat -an
You should get the following two lines related to your program.
Proto Local Address Foreign Address State
tcp 127.0.0.1:65432 0.0.0.0:* LISTEN
udp 127.0.0.1:65432 0.0.0.0:*
In [ f2.c ], the sockets were bound with loopback interface address
127.0.0.1 . If a server uses such a local address, only the users of
that host would be able to access the server.
Terminate the program with CTRL-C.
Replace the string "127.0.0.1" in [f2.c ] with IP address of ethernet
interface of your host.
Compile and run the program
$ gcc -Wall ./f2.c -o two-b
$ ./two-b
In another terminal, record the protocol, local-address and local-port
used by your program.
$ netstat -an
protocol local-address:local-port State
tcp _____________:65432
udp _____________:65432
Terminate the program with CTRL-C.
Use IP address of ethernet interface of your friend's host.
Compile the program
$ gcc -Wall ./f2.c -o ./two-c
Try to run the program
$ ./two-c
[bind] call should fail as such address was not found on the [ eth0 ]
interface of your host.
End of Assignment-3.
A server usually accepts service request, on all available interfaces
of a host. A server binds the socket with addresses of all interfaces
as local addresses.
The program [f3.c] shows such use.
------------------------------------------------------------
// file-name f3.c
// binding with all interfaces
// usage: program-name
#include
#include
#include
#include
#include
#define LOCAL_PORT 65432
int main ( void )
{
int sd1, sd2 ;
int n;
struct sockaddr_in addr; // IPv4 address
// members of [addr] are initialised
addr.sin_family = AF_INET;
addr.sin_port = htons( LOCAL_PORT );
addr.sin_addr.s_addr = htonl( INADDR_ANY );
// TCP ( IPv4 stream ) socket is created
sd1 = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
// TCP socket is bound to a local address
n = bind( sd1, ( struct sockaddr *) &addr, sizeof(addr) );
if( n == -1 ) { perror("bind-call-1"); exit(1); }
// TCP socket is put in listening state
n = listen( sd1, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// UDP ( IPv4 datagram ) socket is created
sd2 = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
// UDP socket is bound to a local address
n = bind( sd2, ( struct sockaddr *) &addr, sizeof(addr) );
if( n == -1 ) { perror("bind-call-2"); exit(1); }
// endless loop
while( 1 ) { sleep(1); }
return 0;
} //end of main
------------------------------------------------------------
htonl() function:
This function converts the long integer from host
byte order to network byte order.
Read its manual.
$ man 3 htonl
Assignment-4:
Compile and run the program
$ gcc -Wall ./f3.c -o ./three
$ ./three
In another terminal, find out local [socket] addresses.
$ netstat -an
tcp 0.0.0.0:65432
udp 0.0.0.0:65432
The address 0.0.0.0 means that the socket is bound to all interfaces
of the host.
Verify this by scanning port 65432 of [lo] interface for TCP and UDP.
# nmap -sTU 127.0.0.1 -p 65432
Likely output is shown:
Interesting ports on localhost (127.0.0.1):
Port State Service
65432/tcp open unknown
65432/udp open unknown
[ eth0 ] interface is also scanned. Replace 172.16.2.146 with the IP
address of the [eth0] interface of your host.
# nmap -sTU 172.16.2.146 -p 65432
Likely output is shown:
Interesting ports on cc-146.cc.cemk.ac.in (172.16.2.146):
Port State Service
65432/tcp open unknown
65432/udp open unknown
Terminate the running program with CTRL-C
End of Assignment-4.
The next program [f4.c] is a TCP [echo] server. This [echo] server is
not using the well-known port ( 7 ), as this is an experiment.
---------------------------------------------------------------------
// file-name f4.c
// TCP ECHO server( iterative )
// usage: program-name
#include
#include
#include
#include
#include
#define LOCAL_PORT 65432
#define BUFFERSIZE 1024 // arbitrary
int main ( void )
{
int serv_sd; // socket descriptor
int temp_sd; // socket descriptor
int n;
struct sockaddr_in serv_addr; // IPv4 address
char buffer[BUFFERSIZE];
ssize_t i,j;
// members of [serv_addr] are initialised
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons( LOCAL_PORT );
serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );
// TCP ( IPv4 stream ) socket is created
serv_sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( serv_sd == -1 ) { perror("socket-call"); exit(1);}
// TCP socket is bound to a local address
n = bind( serv_sd,
( struct sockaddr *) &serv_addr,
sizeof(serv_addr) );
if( n == -1 ) { perror("bind-call"); exit(1); }
// TCP socket is put in listening state
n = listen( serv_sd, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// server accepts client's request in an endless loop
while( 1 )
{
printf( "server: accepting request on TCP port %u\n",
LOCAL_PORT );
temp_sd = accept( serv_sd, NULL, 0 );
if( temp_sd == -1 ) { perror("accept-call"); }
// fill up the buffer with null characters before storing into it
memset( buffer, '\0', BUFFERSIZE );
// read clients request string in the buffer
i = read( temp_sd, buffer, BUFFERSIZE );
printf("server: %u bytes received from client\n", i );
// write the contents of the buffer in the [temp_sd]
j = write( temp_sd, buffer, i );
if( j == -1 ) { perror("write-call"); }
// shutdown both way communication on [temp_sd]
shutdown( temp_sd, SHUT_RDWR );
// remove the now useless [temp_sd]
close( temp_sd );
} //end of endless loop
return 0;
} //end of main
----------------------------------------------------------------------
accept() system call:
This call has three arguments. This call blocks
until a client request arrives on the server's socket. When a request
comes, the call returns a new socket file descriptor. This descriptor
is used for communication with the client.
Read its manual for full description of the call.
$ man 2 accept
In [f4.c], use of 2nd and 3rd arguments are not shown.
Assignment-5:
Compile and run the program.
$ gcc -Wall ./f4.c -o ./four
$ ./four
Request your friend to connect to your [echo] server, using [ telnet ]
client program. Replace 172.16.2.146 with IP address of [ eth0 ]
interface of your host.
friend $ telnet 172.16.2.146 65432
Did your friend get the echo ? ( Y / n )
Stop the [echo] server with CTRL-C.
End of Assignment-5.
TCP [echo] client:
The system calls to be executed by the client and
server, for connection oriented protocol, are repeated below.
SERVER
| CLIENT
socket(), bind(), listen(), accept() |
socket()
| connection establishment |
|<-----------------------------------> connect()
| |
read() <-------------------------------- write()
| data (request from client) |
| |
process client's request |
| |
write()-----------------------------------> read()
data (reply from server)
Figure-1
The program [f5.c] is the TCP [echo] client. This program has to call
[socket] and [connect] calls to establish connection with a server.
Then the client sends request to server and reads reply from server.
In [ f5.c ] the IP address of the [ echo ] server and TCP port of the
[echo] server are supplied as arguments to the program. We know that
assigned number of [echo] server is 7. Still we are using port number
as an argument to the client program. This would enable us to connect
to experimental [echo] servers or to any standard [echo] server.
Save the following file as [f5.c]
-------------------------------------------------------------------
// file-name f5.c
// TCP echo client
// usage -> program-name server-address server-port
#include
#include
#include
#include
#include
#include
#include
#define BUFFERSIZE 1024 // arbitrary
int main(int argc, char *argv[])
{
int sd; // used as socket descriptor
ssize_t i,j;
int n; // used to check returned value
char buffer[BUFFERSIZE];
struct sockaddr_in server_addr; // An IPv4 address
if( argc != 3 )
{
printf("Usage: %s server-address server-port \n", argv[0] );
printf("Example: %s 172.16.2.148 12345 \n", argv[0] );
exit(1);
}
// A TCP ( IPv4 stream ) socket is created.
sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( sd == -1 ) { perror("socket-call"); exit( 1 ); }
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons( atoi(argv[2]) );
n = inet_aton( argv[1], &(server_addr.sin_addr) );
if( n == 0 ) { printf("Invalid address\n"); exit(1); }
n = connect( sd, (struct sockaddr *) &server_addr,
sizeof(server_addr) );
if( n == -1 ) { perror("connect-call"); exit(1); }
/*
The local address of the socket was not set.
[bind()] system call was not called on [sd] before [ connect() ]
system call. As [connect()] was called on a unbound socket, [sd]
was automatically bound to a random free port ( ephemeral port )
with the local address set to [INADDR_ANY].
*/
// generate a prompt
write( STDOUT_FILENO, "Enter the string:", 17 );
// clear buffer before reading
memset( buffer, '\0', BUFFERSIZE );
// read from keyboard in the buffer
i = read( STDIN_FILENO, buffer, BUFFERSIZE );
if( i == -1 ) { perror("read1"); exit(1); }
printf( "bytes read from keyboard=%u\n", i );
// write contents of buffer on server's socket
j = write( sd, buffer, i );
if( j == -1 ) { perror("write1"); exit(1); }
printf("bytes written in server's socket=%u\n",j);
// clear buffer before reading
memset( buffer, '\0', BUFFERSIZE );
// read from server's socket into buffer
i = read( sd, buffer, BUFFERSIZE );
if( i == -1 ) { perror("read2"); exit(1); }
printf("bytes read from server's socket=%un", i );
write( STDOUT_FILENO,"Reply from echo server->", 24 );
j = write( STDOUT_FILENO, buffer, i );
if( j == -1 ) { perror("write2"); exit(1); }
// Shutdown the both-way ( duplex ) connection.
shutdown(sd, SHUT_RDWR);
exit(0);
}
-------------------------------------------------------------------
Function [htons()] takes integer argument. The port number ( argv[2] )
entered as character, is converted into integer.
Assignment-6:
Compile the program
$ gcc -Wall ./f5.c -o ./five
Run the program using wrong number of arguments to see usage message
$ ./five
$ ./five 172.16.2.251
Run the program correctly. Replace 172.16.2.251 with any standard
[echo] server's address. Do not enter a string now.
$ ./five 172.16.2.251 7
From another terminal use [ # netstat -tnp ] command. From the output
of the command, record the line related to your program
Proto Local Address Foreign Address State PID/Program name
Enter a string in the [ echo ] client program. It should be echoed on
your terminal.
Try to connect to a non-existent TCP server in localhost or in another
host. The [ connect ] call of your program should fail with a suitable
error message.
$ ./five 127.0.0.1 2000
$ ./five 172.16.2.251 7777
Try to connect to TCP [echo] servers running on different hosts in the
laboratory or outside the laboratory. Your TCP [echo] client program
should work if TCP [echo] servers are enabled in the specified hosts.
$ ./five 127.0.0.1 7
$ ./five 172.16.2.251 7
$ ./five 172.16.2.252 7
$ ./five 172.16.2.160 7
$ ./five 172.16.1.100 7
$ ./five 210.212.4.3 7
Try to connect to TCP [ echo ] servers running on friend's ECHO server
$ ./five 172.16.2.157 65432
End of Assignment-6.
----------------------------
Optional Assignment-1:
Rename the executable [five] as [tcp-echo-client].
$ mv ./five ./tcp-echo-client
Create a directory [bin] under your home directory
$ mkdir $HOME/bin
Copy the executable in [bin] directory
$ cp ./tcp-echo-client $HOME/bin/
Include the [bin] directory in [PATH] environmental variable
$ PATH=$PATH:$HOME/bin/
Check the intended inclusion with any of the following two commands.
$ echo $PATH
$ env
If the inclusion is correct, you should be able to run the TCP client
from any directory of your account. If you intend to include the [bin]
directory in PATH variable, on every login, include the following line
at the end of file [.bash_profile], in your home directory.
#-- .bash_profile file --
.
.
.
PATH=$PATH:$HOME/bin/
#---------------------------
1. UNIX Network Programming
By W. Richard Stevens
Chapter-6, on Berkeley Sockets
2. Manuals socket(2), ip(7),
tcp(7) and udp(7)
Square brackets are used to separate keywords, such as filenames,
programs names etc etc from lines of text. They have no other meaning.
Go to your home directory
$ cd
Verify the current directory
$ pwd
Create directory [socket1] in your home directory.
$ mkdir socket1
Change into [socket1] directory
$ cd socket1
Bring the file [socket1.txt] in this directory using NFS
$ mount /ftp-server
$ cd /ftp-server
.
.
You may also use [ftp] to bring the file.
SOCKET:
A socket is an endpoint for communication. Sockets are the
primary means of communicating with other hosts; telnet, rlogin, ftp,
talk and the other familiar network programs use sockets.
Different types of [socket]s can be created by [socket()] system call.
Consult the manual of this system call from section 2 of manual.
$ man 2 socket
[socket()] call takes three arguments. An unsigned integer is returned
when the call is successful. This integer is the file descriptor of
the socket. As with regular file descriptors, writing in the socket,
reading from the socket, closing the socket etc etc can be done, using
this descriptor.
Type of the created socket depends on the arguments used. In this
laboratory, we are going to use sockets suitable for network communic-
ation using IPv4 Internet protocols. From the above manual we find
that we have to consult the manual of [ip] from section 7 of the UNIX
manual, for the arguments to be used for creating IPv4 sockets.
$ man 7 ip
A TCP socket ( IPv4 stream socket ) can be created with...
tcp_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
An UDP socket ( IPv4 datagram socket ) can be created with...
udp_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
Zero may be used to replace IPPROTO_TCP and IPPROTO_UDP. Zero is IP
pseudo protocol number.
We are not going to use [raw_socket] in this experiment.
Save the following program as [f1.c].
---------------------------------------------------------------------
// file-name f1.c
// One TCP and one UDP socket are created
// usage: program-name
#include
#include
#include
#include
int main ( void )
{
int sd1, sd2 ;
// sd1 and sd2 would be used as socket-file-descriptors
// Values of two symbolic constants are printed
printf("IPPROTO_TCP = %u \n", IPPROTO_TCP );
printf("IPPROTO_UDP = %u \n", IPPROTO_UDP );
// process number of this program
printf("PID = %u \n", getpid() );
// TCP ( IPv4 stream ) socket is created
sd1 = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
// Numerical value of the socket descriptor is printed
printf("value of TCP socket descriptor = %u \n", sd1 );
// UDP ( IPv4 datagram ) socket is created
sd2 = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
// Numerical value of the socket descriptor is printed
printf("value of UDP socket descriptor = %u \n", sd2 );
// If the program exits, operating system closes (removes) the
// descriptors. The following endless loop is used for checking
// the creation of the two sockets.
while( 1 ) { sleep(1); }
return 0;
} //end of main
---------------------------------------------------------------------
Assignment-1:
Compile the program
$ gcc -Wall ./f1.c -o ./one
Run the executable program, do not terminate the program and record
the following from the output of the program:
$ ./one
IPPROTO_TCP = ___
IPPROTO_UDP = ___
PID = ________
value of TCP socket descriptor = ___
value of UDP socket descriptor = ___
As the program runs in this terminal, this terminal is unusable now.
Note: The program can be started in background also.
$ ./one &
If the program runs in the background, this terminal becomes
usable.
Verify the PID of your program
$ ps ax | grep one
In another terminal, examine the file [/etc/protocols] and record the
following
$ less /etc/protocols
protocols-name protocols-number
IP ------------> ___
TCP -----------> ___
UDP -----------> ___
Check the creation of the sockets with the following command
$ ls -l /proc/value-of-PID/fd
Were the two sockets created ? ( Y / n )
Terminate the running program [one] with CTRL-C.
End of Assignment-1.
5-tuple association for network communication may be stated as:
(protocol,local-address,local-process,foreign-address,foreign-process)
Assignment-2.
In this assignment, a 5-tuple association for network
communication is to be verified. The [echo] server process using TCP,
running in your friend's host, are the [ foreign-address ], [ foreign-
process ] and [ protocol ].
Examine file [/etc/services] and record:
$ less /etc/services
[echo] server, using TCP protocol, runs on port number ____ .
[foreign-process] is NOT the PID of the [echo] server process, but it
is the port number, the [echo] server process associates with. If the
[ echo ] server process is restarted, its PID would change but its
association with port number - 7 would be unaltered. This port number
is well-known to the [ client/clients ].
At present we do not have any TCP [echo] client program. Later in this
experiment we are going to write a TCP [echo] client program.
[telnet] is a [client] program used to connect to the [telnetd] server
program. [ telnet ] connects to port-23 of the specified host, if port
number is not specified. If port number is specified, [ telnet ]
connects to that port.
The two commands should give the same result
$ telnet 192.168.5.145
or
$ telnet 172.16.2.145 23
If port number is specified as 7, [ telnet ] program may be used to
communicate with the [echo] server. Replace 172.16.2.145 with the IP
address of your friend's host.
$ telnet 172.16.2.145 7
Enter any string. It should be echoed on your terminal.
[ telnet ] program used in your host, is the [ local-process ]. PID of
[telnet] process is NOT the [[local-process], it is the port number it
is associated with. This port number ( in the range 1024 - 65535 ) is
alloted to that instance of [telnet] process, by the operating system
and it is guaranteed to be free, no other process using TCP protocol
was using it. The port assigned to the [ client ] process is called
ephemeral ( short lived ) port. The PID and the ephemeral port might
change with each invocation of the [client] process.
----------- ----------------
| | | |
| Your host |_____________________| Friend's Host |
| client | | echo server(7) |
| | | |
----------- ----------------
Connect to the [ echo ] server of your friend but do not enter any
string. In this condition a TCP connection is established.
$ telnet 172.16.2.145 7
In another terminal, login in your account ( or login as [root] ) and
use the following command.
$ ps ax
PID of the [telnet] process -->
Use the following command...
$ netstat -atnp
You may read manual of this command [ $ man 8 netstat ].
The meaning of the options are reproduced from the manual:
a all
t TCP
n numeric output
p show PID and program name
If the output is more than one screenful, you can store the result in
a file and examine the file with a pager, such as [less].
$ netstat -atnp >tmp 2>&1
$ less ./tmp
Fill up the following table.
proto loc-add:loc-port for-add:for-port state PID/prog-name
tcp :7 ESTABLISHED
The above is the 5-tuple association.
End of Assignment-2.
The system calls used by the [server] and the [client] for connection
oriented protocol are shown below ( From "UNIX Network Programming" by
W.Richard Stevens ). TCP is a connection oriented protocol.
SERVER
socket()
|
bind()
|
listen()
|
accept() CLIENT
|
Blocks until connection socket()
from client |
| connection establishment |
|<-----------------------------------------> connect()
| |
read() <------------------------------------- write()
| data (request from client) |
| |
process client's request |
| |
write() --------------------------------------> read()
data (reply from server)
A newly created socket is not useful for communication. An address is
to be assigned to it.
The format of a IPv4 address is reproduces from manual [ip(7)].
struct sockaddr_in
{
sa_family_t sin_family; // address family: AF_INET
u_int16_t sin_port; // port in network byte
struct in_addr sin_addr; // internet address
};
// Internet address.
struct in_addr {
u_int32_t s_addr; // address in network byte order
};
Internet address and port number are to be in a format, called the
"network byte order".
When the members of a IPv4 address have been initialised, the newly
created socket is associated with this address, with [ bind ] system
call. [ bind ] call sets a local IP address and port number of the
socket. When it is needed to assign a specific port ( well-known) to a
socket, [bind] is used. Well-known ports are used by servers. [ bind ]
call is mainly used by servers.
[bind] call takes three arguments
int = bind( socket-descriptor,
address of local IPv4 address,
size of the IPv4 address in bytes )
You may read manual of bind(2)] for the exact syntax of the call.
[listen] system call makes a [socket] ready to accept incoming client
requests. [ listen ] call also sets a limit of the incoming connection
queue. [listen] call is valid for connection oriented protocols (TCP).
In the next program [f2.c] following are done:
One TCP and one UDP
socket are created. Members of the structure of one IPv4 address are
then initialised. This address is assigned to the UDP and TCP sockets.
Although the same IP address and port number are used, the two sockets
are bound to two different addresses, as two different protocols are
used. The TCP [socket] is put in listening state.
------------------------------------------------------------
// file-name f2.c
// bind() and listen() calls
// usage: program-name
#include
#include
#include
#include
#include
#define LOCAL_ADDRESS "127.0.0.1"
// 127.0.0.1 is the IP address of loopback interface
// Any free port ( 1024 to 65535 ) is chosen
#define LOCAL_PORT 65432
int main ( void )
{
int sd1, sd2 ;
int n;
struct sockaddr_in addr; // IPv4 address
// members of [addr] are initialised
addr.sin_family = AF_INET;
addr.sin_port = htons( LOCAL_PORT );
n = inet_aton( LOCAL_ADDRESS , &(addr.sin_addr) );
if( n == 0 )
{
printf("invalid-addr\n");
exit(1);
}
// TCP ( IPv4 stream ) socket is created
sd1 = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
// TCP socket is bound to a local address
n = bind( sd1, ( struct sockaddr *) &addr, sizeof(addr) );
if( n == -1 ) { perror("bind-call-1"); exit(1); }
// TCP socket is put in listening state
n = listen( sd1, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// UDP ( IPv4 datagram ) socket is created
sd2 = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
// UDP socket is bound to a local address
n = bind( sd2, ( struct sockaddr *) &addr, sizeof(addr) );
if( n == -1 ) { perror("bind-call-2"); exit(1); }
// endless loop
while( 1 ) { sleep(1); }
return 0;
} //end of main
---------------1---------------------------------------------
htons() function:
This function converts the short integer from host
byte order to network byte order. Port numbers are 16 bit long.
Read its manual.
$ man 3 htons
inet_aton() function:
This function converts the Internet host address
from the standard numbers-and-dots notation into binary data and
stores it in the address structure. This function returns nonzero if
the address is valid, zero if not.
Read its manual.
$ man 3 inet_aton
Assignment-3:
Compile and run the program.
$ gcc -Wall ./f2.c -o ./two-a
$ ./two-a
Use the following command and examine the output
$ netstat -an
You should get the following two lines related to your program.
Proto Local Address Foreign Address State
tcp 127.0.0.1:65432 0.0.0.0:* LISTEN
udp 127.0.0.1:65432 0.0.0.0:*
In [ f2.c ], the sockets were bound with loopback interface address
127.0.0.1 . If a server uses such a local address, only the users of
that host would be able to access the server.
Terminate the program with CTRL-C.
Replace the string "127.0.0.1" in [f2.c ] with IP address of ethernet
interface of your host.
Compile and run the program
$ gcc -Wall ./f2.c -o two-b
$ ./two-b
In another terminal, record the protocol, local-address and local-port
used by your program.
$ netstat -an
protocol local-address:local-port State
tcp _____________:65432
udp _____________:65432
Terminate the program with CTRL-C.
Use IP address of ethernet interface of your friend's host.
Compile the program
$ gcc -Wall ./f2.c -o ./two-c
Try to run the program
$ ./two-c
[bind] call should fail as such address was not found on the [ eth0 ]
interface of your host.
End of Assignment-3.
A server usually accepts service request, on all available interfaces
of a host. A server binds the socket with addresses of all interfaces
as local addresses.
The program [f3.c] shows such use.
------------------------------------------------------------
// file-name f3.c
// binding with all interfaces
// usage: program-name
#include
#include
#include
#include
#include
#define LOCAL_PORT 65432
int main ( void )
{
int sd1, sd2 ;
int n;
struct sockaddr_in addr; // IPv4 address
// members of [addr] are initialised
addr.sin_family = AF_INET;
addr.sin_port = htons( LOCAL_PORT );
addr.sin_addr.s_addr = htonl( INADDR_ANY );
// TCP ( IPv4 stream ) socket is created
sd1 = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
// TCP socket is bound to a local address
n = bind( sd1, ( struct sockaddr *) &addr, sizeof(addr) );
if( n == -1 ) { perror("bind-call-1"); exit(1); }
// TCP socket is put in listening state
n = listen( sd1, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// UDP ( IPv4 datagram ) socket is created
sd2 = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
// UDP socket is bound to a local address
n = bind( sd2, ( struct sockaddr *) &addr, sizeof(addr) );
if( n == -1 ) { perror("bind-call-2"); exit(1); }
// endless loop
while( 1 ) { sleep(1); }
return 0;
} //end of main
------------------------------------------------------------
htonl() function:
This function converts the long integer from host
byte order to network byte order.
Read its manual.
$ man 3 htonl
Assignment-4:
Compile and run the program
$ gcc -Wall ./f3.c -o ./three
$ ./three
In another terminal, find out local [socket] addresses.
$ netstat -an
tcp 0.0.0.0:65432
udp 0.0.0.0:65432
The address 0.0.0.0 means that the socket is bound to all interfaces
of the host.
Verify this by scanning port 65432 of [lo] interface for TCP and UDP.
# nmap -sTU 127.0.0.1 -p 65432
Likely output is shown:
Interesting ports on localhost (127.0.0.1):
Port State Service
65432/tcp open unknown
65432/udp open unknown
[ eth0 ] interface is also scanned. Replace 172.16.2.146 with the IP
address of the [eth0] interface of your host.
# nmap -sTU 172.16.2.146 -p 65432
Likely output is shown:
Interesting ports on cc-146.cc.cemk.ac.in (172.16.2.146):
Port State Service
65432/tcp open unknown
65432/udp open unknown
Terminate the running program with CTRL-C
End of Assignment-4.
The next program [f4.c] is a TCP [echo] server. This [echo] server is
not using the well-known port ( 7 ), as this is an experiment.
---------------------------------------------------------------------
// file-name f4.c
// TCP ECHO server( iterative )
// usage: program-name
#include
#include
#include
#include
#include
#define LOCAL_PORT 65432
#define BUFFERSIZE 1024 // arbitrary
int main ( void )
{
int serv_sd; // socket descriptor
int temp_sd; // socket descriptor
int n;
struct sockaddr_in serv_addr; // IPv4 address
char buffer[BUFFERSIZE];
ssize_t i,j;
// members of [serv_addr] are initialised
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons( LOCAL_PORT );
serv_addr.sin_addr.s_addr = htonl( INADDR_ANY );
// TCP ( IPv4 stream ) socket is created
serv_sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( serv_sd == -1 ) { perror("socket-call"); exit(1);}
// TCP socket is bound to a local address
n = bind( serv_sd,
( struct sockaddr *) &serv_addr,
sizeof(serv_addr) );
if( n == -1 ) { perror("bind-call"); exit(1); }
// TCP socket is put in listening state
n = listen( serv_sd, 5 );
if( n == -1 ) { perror("listen-call"); exit(1); }
// server accepts client's request in an endless loop
while( 1 )
{
printf( "server: accepting request on TCP port %u\n",
LOCAL_PORT );
temp_sd = accept( serv_sd, NULL, 0 );
if( temp_sd == -1 ) { perror("accept-call"); }
// fill up the buffer with null characters before storing into it
memset( buffer, '\0', BUFFERSIZE );
// read clients request string in the buffer
i = read( temp_sd, buffer, BUFFERSIZE );
printf("server: %u bytes received from client\n", i );
// write the contents of the buffer in the [temp_sd]
j = write( temp_sd, buffer, i );
if( j == -1 ) { perror("write-call"); }
// shutdown both way communication on [temp_sd]
shutdown( temp_sd, SHUT_RDWR );
// remove the now useless [temp_sd]
close( temp_sd );
} //end of endless loop
return 0;
} //end of main
----------------------------------------------------------------------
accept() system call:
This call has three arguments. This call blocks
until a client request arrives on the server's socket. When a request
comes, the call returns a new socket file descriptor. This descriptor
is used for communication with the client.
Read its manual for full description of the call.
$ man 2 accept
In [f4.c], use of 2nd and 3rd arguments are not shown.
Assignment-5:
Compile and run the program.
$ gcc -Wall ./f4.c -o ./four
$ ./four
Request your friend to connect to your [echo] server, using [ telnet ]
client program. Replace 172.16.2.146 with IP address of [ eth0 ]
interface of your host.
friend $ telnet 172.16.2.146 65432
Did your friend get the echo ? ( Y / n )
Stop the [echo] server with CTRL-C.
End of Assignment-5.
TCP [echo] client:
The system calls to be executed by the client and
server, for connection oriented protocol, are repeated below.
SERVER
| CLIENT
socket(), bind(), listen(), accept() |
socket()
| connection establishment |
|<-----------------------------------> connect()
| |
read() <-------------------------------- write()
| data (request from client) |
| |
process client's request |
| |
write()-----------------------------------> read()
data (reply from server)
Figure-1
The program [f5.c] is the TCP [echo] client. This program has to call
[socket] and [connect] calls to establish connection with a server.
Then the client sends request to server and reads reply from server.
In [ f5.c ] the IP address of the [ echo ] server and TCP port of the
[echo] server are supplied as arguments to the program. We know that
assigned number of [echo] server is 7. Still we are using port number
as an argument to the client program. This would enable us to connect
to experimental [echo] servers or to any standard [echo] server.
Save the following file as [f5.c]
-------------------------------------------------------------------
// file-name f5.c
// TCP echo client
// usage -> program-name server-address server-port
#include
#include
#include
#include
#include
#include
#include
#define BUFFERSIZE 1024 // arbitrary
int main(int argc, char *argv[])
{
int sd; // used as socket descriptor
ssize_t i,j;
int n; // used to check returned value
char buffer[BUFFERSIZE];
struct sockaddr_in server_addr; // An IPv4 address
if( argc != 3 )
{
printf("Usage: %s server-address server-port \n", argv[0] );
printf("Example: %s 172.16.2.148 12345 \n", argv[0] );
exit(1);
}
// A TCP ( IPv4 stream ) socket is created.
sd = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
if( sd == -1 ) { perror("socket-call"); exit( 1 ); }
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons( atoi(argv[2]) );
n = inet_aton( argv[1], &(server_addr.sin_addr) );
if( n == 0 ) { printf("Invalid address\n"); exit(1); }
n = connect( sd, (struct sockaddr *) &server_addr,
sizeof(server_addr) );
if( n == -1 ) { perror("connect-call"); exit(1); }
/*
The local address of the socket was not set.
[bind()] system call was not called on [sd] before [ connect() ]
system call. As [connect()] was called on a unbound socket, [sd]
was automatically bound to a random free port ( ephemeral port )
with the local address set to [INADDR_ANY].
*/
// generate a prompt
write( STDOUT_FILENO, "Enter the string:", 17 );
// clear buffer before reading
memset( buffer, '\0', BUFFERSIZE );
// read from keyboard in the buffer
i = read( STDIN_FILENO, buffer, BUFFERSIZE );
if( i == -1 ) { perror("read1"); exit(1); }
printf( "bytes read from keyboard=%u\n", i );
// write contents of buffer on server's socket
j = write( sd, buffer, i );
if( j == -1 ) { perror("write1"); exit(1); }
printf("bytes written in server's socket=%u\n",j);
// clear buffer before reading
memset( buffer, '\0', BUFFERSIZE );
// read from server's socket into buffer
i = read( sd, buffer, BUFFERSIZE );
if( i == -1 ) { perror("read2"); exit(1); }
printf("bytes read from server's socket=%un", i );
write( STDOUT_FILENO,"Reply from echo server->", 24 );
j = write( STDOUT_FILENO, buffer, i );
if( j == -1 ) { perror("write2"); exit(1); }
// Shutdown the both-way ( duplex ) connection.
shutdown(sd, SHUT_RDWR);
exit(0);
}
-------------------------------------------------------------------
Function [htons()] takes integer argument. The port number ( argv[2] )
entered as character, is converted into integer.
Assignment-6:
Compile the program
$ gcc -Wall ./f5.c -o ./five
Run the program using wrong number of arguments to see usage message
$ ./five
$ ./five 172.16.2.251
Run the program correctly. Replace 172.16.2.251 with any standard
[echo] server's address. Do not enter a string now.
$ ./five 172.16.2.251 7
From another terminal use [ # netstat -tnp ] command. From the output
of the command, record the line related to your program
Proto Local Address Foreign Address State PID/Program name
Enter a string in the [ echo ] client program. It should be echoed on
your terminal.
Try to connect to a non-existent TCP server in localhost or in another
host. The [ connect ] call of your program should fail with a suitable
error message.
$ ./five 127.0.0.1 2000
$ ./five 172.16.2.251 7777
Try to connect to TCP [echo] servers running on different hosts in the
laboratory or outside the laboratory. Your TCP [echo] client program
should work if TCP [echo] servers are enabled in the specified hosts.
$ ./five 127.0.0.1 7
$ ./five 172.16.2.251 7
$ ./five 172.16.2.252 7
$ ./five 172.16.2.160 7
$ ./five 172.16.1.100 7
$ ./five 210.212.4.3 7
Try to connect to TCP [ echo ] servers running on friend's ECHO server
$ ./five 172.16.2.157 65432
End of Assignment-6.
----------------------------
Optional Assignment-1:
Rename the executable [five] as [tcp-echo-client].
$ mv ./five ./tcp-echo-client
Create a directory [bin] under your home directory
$ mkdir $HOME/bin
Copy the executable in [bin] directory
$ cp ./tcp-echo-client $HOME/bin/
Include the [bin] directory in [PATH] environmental variable
$ PATH=$PATH:$HOME/bin/
Check the intended inclusion with any of the following two commands.
$ echo $PATH
$ env
If the inclusion is correct, you should be able to run the TCP client
from any directory of your account. If you intend to include the [bin]
directory in PATH variable, on every login, include the following line
at the end of file [.bash_profile], in your home directory.
#-- .bash_profile file --
.
.
.
PATH=$PATH:$HOME/bin/
#---------------------------
Subscribe to:
Posts (Atom)
