Anda di halaman 1dari 11

PENDAHULUAN

Sasaran pembelajaran dalam bab ini adalah :


 Komunikasi antara client dengan server

 Contoh lengkap sebuah TCP client sederhana

 Contoh lengkap sebuah TCP server yang bekerja dengan client

pada point 2 di atas


 Fungsi-fungsi pembungkus milik kita sendiri

 Sebagian besar bahasan UNIX, termasuk istilah POSIX.

HUBUNGAN KOMUNIKASI CLIENT SERVER

Sebagian besar aplikasi jaringan dapat dibagi ke dalam 2 bagian :


 Client
 Server
Contoh Client Server :
 Sebuah web browser (client) berkomunikasi dgn sebuah web

server
 Sebuah FTP client menjemput sebuah file dari sebuah FTP

server
 Sebuah Telnet client yang digunakan untuk login ke sebuah

host jauh melalui sebuah Telnet server pada host jauh tsb.

Bagaimana bentuk hubungan komunikasi di antara keduanya ?

Hubungan komunikasi
client server

Gambar 1.1. Aplikasi Jaringan : Client dan Server

Normalnya, client-client berkomunikasi dengan satu server pada


satu saat, meskipun, sbg contoh, dengan menggunakan web
browser kita mungkin berkomunikasi dengan banyak web server,
katakanlah setiap periode waktu 10 menit. Dan pada sembarang
waktu yang diberikan, adalah tidak biasanya bagi server untuk
berkomunikasi dengan client-client jamak.

client

---
client server

---
client

Gambar 1.2. Server Menangani Client Jamak pada Saat yang Sama
Application protocol
User web web
process client server application
layer
TCP protocol
TCP TCP transport layer
Protocol
stack
within IP protocol
kernel network
IP IP layer

Ethernet protocol
Ethernet Ethernet
driver driver
datalink
layer
Actual flow between
client and server

Ethernet

Gambar 1.3. Client dan Server pada Ethernet yang Sama


Berkomunikasi dengan Menggunakan TCP

Client Server
application application

Host with Host with


TCP/IP TCP/IP

LAN LAN

Router Router

WAN
Router Router Router Router

Gambar 1.4. Client dan Server pada LAN Berbeda Terhubung Melalui
WAN
MODEL JARINGAN

Application
detail
Application Soket User
Presentation Application XTI process
Session
Transport TCP UDP
Network IPv4, IPv6 Kernel
Data Link Device driver Communications
Physical & hardware details

Gambar Lapisan-lapisan dalam Model OSI dan Suita Protokol Internet

 Sebuah jarak antara TCP & UDP menunjukkan bahwa mungkin


saja bagi aplikasi untuk menghindari lapisan transport dan
langsung menggunakan Ipv4 atau Ipv6. Ini disebut soket mentah.
 Dua antarmuka pemrograman; Soket & XTI; adalah antarmuka-
antarmuka dari ke-3 lapisan atas (“aplikasi”) ke lapisan transport.

Mengapa baik soket maupun XTI menyediakan antarmuka dari ke-3


lapisan atas (“aplikasi”) ke lapisan transport ? Alasan :
 3 lapisan atas menangani detail-detail aplikasi, hanya mengetahui
sedikit tentang detail-detail komunikasi. Empat lapisan bawah
mengetahui sedikit tentang detail-detail aplikasi, menangani
semua detail komunikasi.
 Ke-3 lapisan atas membentuk apa yang disebut proses pengguna.
UNIX & sistem operasi lain yang sebaya menyediakan pemisahan
antara proses pengguna dgn kernel.
 Kesimpulan : antarmuka antara lapisan 4 & 5 adalah tempat yang
alami untuk membangun API.

SEJARAH JARINGAN BSD


 Soket-soket API berasal mula dari sistem 4.2 BSD
 Sedikit perubahan atas soket-soket API juga terjadi pada release
4.3 BSD Reno, ketika protokol-protokol OSI masuk ke kernel BSD.
 Dari 4.2. BSD s.d 4.4 BSD adalah release-release dari Computer
System Research Group (CSRG) pada Berkeley yang meminta
penerima untuk memiliki lisensi kode sumber untuk UNIX.
 Th 1989 Berkeley menyediakan release jaringan BSD yang
pertama, berisikan semua kode jaringan dan berbagai potongan
sistem BSD lainnya yang tidak dibatasi oleh lisensi kode sumber
UNIX.
 Release akhir dari Berkeley adalah 4.4 BSD-Lite & 4.4 BSD-Lite2.
Lalu ke-2nya digunakan sbg dasar dari sistem-sistem lain :
BSD/OS, FreeBSD, NetBSD, & OpenBSD.
 Banyak sistem UNIX dimulai dgn beberapa versi dari kode jaringan
BSD, termasuk soket-soket API, & kita mengacu kepada
implementasinya sbg Berkeley-derived implementation.
 Banyak versi komersial dari UNIX berdasarkan pada System V
Release 4 (SVR 4), beberapa darinya memiliki kode jaringan
Berkeley-derived (misal : UnixWare 2.x) ketika kode jaringan dlm
sistem SVR4 secara mandiri juga telah diperoleh (misal : Solaris
2.x)

4.2 BSD (1983)


First widely available release of
TCP/IP and sockets API

4.3 BSD (1986)


TCP performance improvements

4.3 BSD Tahoe (1988)


slow start, congestion
avoidance, fast retransmit

BSD Networking software 4.3 BSD Reno (1990)


Release 1.0 (1989): Net/1 fast recovery, TCP header
prediction, SLIP header
compression,routing table
changes; length field added to
sockaddr { }, control information
added to msghdr { }
BSD Networking software
Release 2.0 (1991): Net/2

4.4 BSD (1993)


multicasting, long fat pipe
modifications

4.4 BSD-Lite (1994)


referred to in text as Net/3 BSD / OS
FreeBSD
NetBSD
OpenBSD
4.4 BSD-Lite2 (1991)

Gambar Sejarah dari Bermacam-macam Release BSD

STANDARD-STANDAR UNIX
POSIX (Portable Operating System Interface)
 IEEE Standard 1003.1 – 1988
Menspesifikasikan antarmuka bahasa C ke dalam sebuah kernel
serupa-UNIX, meliputi area-area sbb :
 Primitif-primitif proses (fork, exec, signals, timers)
 Lingkungan dari sebuah proses (User IDs, process groups)
 File & direktori (semua fungsi I/O)
 Basisdata-basisdata sistem (password file & group file)
 Format archieve tar & cpio
 IEEE Std 1003.1 – 1990
Juga dikenal sbg standard Internasional ISO/IEC 9945-1 : 1990.
Terdapat perubahan-perubahan minimal. Standard ini adalah API
bahasa C.
 IEEE Std 1003.2 – 1992
Judulnya berisikan : “Part 2 : Shell & Utilities”. Bagian ini
mendefinisikan Shell (berdasarkan pada Shell V Bourne System) &
sekitar 100 Utilitas.
 Dalam bahasan kita, kita merujuk ke standard ini sbg Posix.2.
 IEEE Std 1003.1b – 1993
Dulunya dikenal sbg IEEE P1003.4 . Pembaharuan : memasukkan
ekstensi-ekstensi real-time yg dibangun oleh kelompok kerja
P1003.4. Item-item yg ditambahkan :
 Sinkronisasi File
 I/O asinkron
 Semaphore
 Manajemen memori (mmap & memori bersama)
 Penjadwalan eksekusi
 Clock & timers
 & antrian pesan
 IEEE Std 1003.1, edisi 1996 [IEEE 1996]
Juga disebut ISO/IEC 9945-1: 1996
Berisikan :
 1003.1 – 1990 (API dasar)
 1003.1b – 1993 (ekstensi-ekstensi real-time)
 1003.1c – 1995 (pthreads)
 1003.1i – 1995 (koreksi-koreksi teknis terhadap 1003.1b)
 Dalam bahasan kita, kita merujuk ke standard ini sbg Posix.1.

Kerja POSIX yg mempengaruhi sebagian besar bahasan kita


adalah IEEE Std 1003.1g : Protocol Independent Interface (PII) yg
merupakan produk dari kelompok kerja P1003.1g. Ini adalah
standard-standard API jaringan & ia mendefinisikan 2 API yang
disebut DNIs (Detailed Network Interfaces) :
 DNI/Socket, berdasarkan pada soket-soket 4.4 BSD API.
 DNI/XTI, berdasarkan pada spesifikasi XPG4 X/Open.

Versi-versi UNIX dan Portabilitas


Secara sejarah, sebagian besar sistem UNIX menampilkan baik
sebuah warisan Berkeley maupun sebuah warisan V system, tapi
perbedaan-perbedaan ini perlahan-lahan menghilang disebabkan
sebagian besar vendor mengadopsi standard-standard POSIX
(Perbedaan-perbedaan utama yang berurusan dengan administrasi
sistem masih ada).
 Fokus bahasan kita adalah pada standard Posix 1.g, dengan
fokus utama kita pada soket-soket API. Kapanpun memungkinkan,
kita gunakan fungsi-fungsi POSIX.

SEBUAH DAYTIME CLIENT SEDERHANA


Client ini membangun sebuah koneksi TCP dengan sebuah server dan
server secara sederhana mengirim kembali waktu & tanggal saat ini
dalam format yang dapat dibaca manusia.
Jika kita mengkompilasi program ke dalam file default a.out dan
menjalankannya, kita akan memperoleh output sbb :

Solaris % a.out 206.62.226.35 input kita


Fri Des 29 14:27:52 2017 ouput program

Intro/daytimetcpcli.c
1 #include “unp.h”

2 int
3 main(int argc, char **argv)
4 {
5 int sockfd, n;
6 char recvline[MAXLINE + 1];
7 struct sockaddr_in servaddr;

8 if (argc != 2 )
9 err_quit(“usage: a.out <IPaddress>”);

10 if ((sockfd = socket(AF_INET, SOCK_STREAM, 0 )) < 0 )


11 err_sys(“socket error”);

12 bzero(&servaddr, sizeof (servaddr) ) ;


13 servaddr.sin_family = AF_INET;
14 servaddr.sin_port = htons(13); /* daytime server */
15 if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
16 err_quit(“inet_pton error for %s” , argv[1]);

17 if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)


18 err_sys( “connect error” );

19 while ((n = read(sockfd, recvline, MAXLINE)) > 0) {


20 recvline[n] = 0; /* null terminate */
21 if (fputs(recvline, stdout) == EOF)
22 err_sys(“fputs error”);
23 }
24 if (n < 0)
25 err_sys(“read error”);

26 exit(0);
27 }
Intro/daytimetcpcli.c
Menyertakan Header Kita Sendiri
1 Kita menyertakan header kita sendiri unp.h. Header ini berisikan
bermacam-macam header sistem yg dibutuhkan oleh sebagian
besar program-program jaringan & mendefinisikan bermacam-
macam konstanta yg kita gunakan (misal : MAXLINE)

Argumen-argumen Baris Perintah


2-3 Ini adalah definisi dari fungsi main, berikut dengan argumen-
argumen baris perintah.

Menciptakan Sebuah Soket TCP


10- Fungsi Socket menciptakan sebuah socket stream
11 (SOCK_STREAM)Internet (AF_INET) yang merupakan sebuah
nama ilustrasi untuk sebuah soket TCP.
Jika pemanggilan ke soket gagal, kita membatalkan program
dengan memanggil fungsi err_sys kita sendiri.

Menspesifikasikan IP Address & Port Server


12- Kita isi sebuah struktur alamat soket Internet (sebuah struktur
16 sockaddr_in dinamakan servadddr) dengan IP address &
port number server.
Kita atur struktur ke nol dgn menggunakan bzero.
Kita mengatur keluarga alamat ke AF_INET, mengatur port
number ke 13 (yg merupakan well-known port number pada
daytime server pada sembarang host TCP/IP yg mendukung
layanan ini) & mengatur IP address ke nilai tertentu.

Membangun Koneksi dengan Server


17- Fungsi connect, ketika diaplikasikan ke sebuah soket TCP,
18 membangun sebuah koneksi TCP dgn server yg dispesifikasikan.

Membaca dan Menampilkan Jawaban Server


19- Kita read jawaban server & menampilkan hasil menggunakan
25 fungsi fputs standard I/O.

Mengakhiri Program
26 Exit mengakhiri program. UNIX selalu menutup seluruh
descriptor yg terbuka ketika sebuah proses berakhir, jadi soket
TCP kita sekarang ditutup.

Bahasan kita menuju detail-detail yang lebih banyak lagi, pada semua
point yang baru kita bahas tadi.

PENANGANAN KESALAHAN : MEMBUNGKUS FUNGSI-FUNGSI


Karena terminasi pada sebuah kesalahan adalah suatu hal yg umum,
kita dapat memendekkan program kita dgn mendefinisikan sebuah
fungsi pembungkus yg membentuk pemanggilan fungsi sebenarnya,
menguji nilai yg dikembalikan & terminasi pada sebuah kesalahan.
Kebiasaan yg kita gunakan adalah menuliskan nama fungsi dgn huruf
besar, seperti dalam :

Sockfd = Socket (AF_INET, SOCK_STREAM, 0);

Fungsi pembungkus milik kita memanggil sebuah fungsi yg memiliki


nama yang sama tetapi dimulai dengan huruf kecil.

Lib/wrapsock.c
172 Int
173 Socket(int family, int type, int protocol)
174 {
175 int n;

176 if ( (n = socket(family, type, protocol)) <


0)
177 err_sys(“socket error”);
178 return (n);
179 }

Gambar 1.7. Fungsi Pembungkus Kita untuk Fungsi socket

NILAI errno UNIX


Saat sebuah kesalahan terjadi dalam sebuah fungsi UNIX, variable
global errno diatur ke nilai positif untuk mengindikasikan jenis
kesalahan dan normalnya fungsi mengembalikan nilai –1.

 Semua nilai kesalahan positif adalah konstanta, dengan sebuah


nama yang dimulai dengan E dan semua berhuruf besar, dan
normalnya ditentukan dalam header <sys/errno.h>.
 Tidak ada kesalahan yang bernilai nol.

Fungsi err_sys kita melihat nilai errno dan mencetak string


pesan kesalahan yang sesuai. Contoh : “Connection time out” jika
errno sebanding dengan ETIMEOUT).

CONTOH PENGGUNAAN LAIN FUNGSI PEMBUNGKUS


Fungsi-fungsi thread tidak mengatur variable errno standard UNIX
ketika sebuah kesalahan terjadi. Sebagai gantinya adalah nilai yang
dikembalikan oleh fungsi. Ini berarti bahwa setiap kali kita memanggil
salah satu dari fungsi pthread maka kita harus :
 Mengalokasikan sebuah variable
 Menyimpan nilai yang dikembalikan ke dalam variable itu
 Mengatur errno ke nilai ini sebelum memanggil err_sys

Program :
int n;
if ((n = pthread_mutex_lock(&ndone_mutex)) != 0)
errno = n, err_sys(“pthread_mutex_lock error’);

Sebagai alternatifnya, kita dapat mendefinisikan sebuah fungsi


pembungkus untuk fungsi-fungsi thread ini, yang yang mengambil
angka kesalahan sebagai sebuah argumen.

Lib/wrappthread.c
72 void
73 Pthread_mutex_lock(pthread_mutex_t *mptr)
74 {
75 int n;

76 if ( (n = pthread_mutex_lock(mptr)) == 0)
77 return;
78 errno = n;
79 err_sys (“pthread_mutex_lock error”);
80 }

Maka kita dapat membuat potongan kode dalam program kita


menjadi jauh lebih mudah untuk dibaca, hanya sebagai :

Pthread_mutex_lock(&ndone_mutex);

Kita menggunakan fungsi-fungsi pembungkus ini kecuali jika kita


butuh untuk memeriksa bagi sebuah kesalahan eksplisit dan
menanganinya dalam bentuk selain terminasi proses.

Sebuah Daytime Server Sederhana

Menciptakan Sebuah Soket TCP


10 Penciptaan soket TCP identik dengan kode client

Mengikat Well-known Port Server ke Soket


11- Well-known port (13 untuk layanan daytime) diikat ke soket dgn
15 mengisi sebuah struktur alamat soket Internet dan memanggil
bind. Kita menspesifikasikan alamat IP sbg INADDR_ANY, yg
mengizinkan server utk menerima sebuah koneksi client pada
sembarang antarmuka, dlm kasus server memiliki antarmuka
jamak.

Mengubah Soket ke Listening Soket


16 Dengan memanggil listen, soket dikonversi ke dalam sebuah
listening soket, dimana padanya koneksi yang datang dari client
akan diterima oleh kernel.
Tiga langkah ini; socket, bind, & listen; adalah
langkah-langkah normal untuk sembarang server TCP untuk
menyiapkan apa yg kita sebut listening descriptor (dlm contoh
ini : listenfd)
Konstanta LISTENQ adalah dari header unp.h kita.
Ia menspesifikasikan angka maksimum dari koneksi-koneksi
client yang akan kernel antrikan untuk listening descriptor.

Menerima Koneksi Client, Mengirim Jawaban


17- Normalnya proses server dijadikan ‘tidur’ dalam panggilan
21 accept, menunggu sebuah koneksi client tiba dan diterima.
Sebuah koneksi TCP memakai apa yg disebut sbg three way
handshake untuk membangun sebuah koneksi dan ketika
handshake ini selesai, accept kembali, & nilai yg dikembalikan
dari fungsi ini adalah sebuah descriptor baru (connfd) yaitu
disebut connected descriptor. Sebuah deskriptor baru
dikembalikan oleh accept untuk tiap client yg berkoneksi dgn
server kita.
Waktu & tgl dikembalikan oleh fungsi library time. Fungsi
library ctime mengkonversi nilai integer ini ke dlm string yg
dpt dibaca manusia, spt : Fri Jan 12 14:27:52 2000.
Sebuah carriage return & linefeed ditambahkan ke string oleh
snprintf & hasil ditulis ke client oleh write.

Mengakhiri Koneksi
22 Server menutup koneksinya dgn client dgn memanggil close.
Ini mengawali urutan terminasi koneksi TCP : sebuah FIN
dikirimkan dalam setiap arah & setiap FIN disahkan (ack) oleh
pihak ujung lainnya.

 Sebagaimana dengan client, server adalah protokol yg bergantung


IPv4.
 Server kita hanya menangani satu client pada satu saat. Jika
koneksi client jamak tiba pada saat yang hampir berbarengan,
kernel mengantrikan mereka hingga batas waktu tertentu dan
mengembalikan mereka ke accept satu client pada satu saat.
Server ini disebut server iteratif karena ia mengiterasi melewati
tiap client, 1 client pada 1 saat.

TCP daytime server

Intro/daytimetcpsrv.c
1 #include “unp.h”
2 #include <time.h>

3 int
4 main (int argc, char **argv)
5 {
6 int listenfd, connfd;
7 struct sockaddr_in servaddr;
8 char buff[MAXLINE]
9 time_t ticks;

10 Listenfd = Socket (AF_INET, SOCK_STREAM, 0);

11 bzero (&servaddr, sizeof(servaddr));


12 servaddr.sin_family = AF_INET;
13 servaddr.sin_addr.s_addr = htonl
(INADDR_ANY);
14 servaddr.sin_port = htons(13); /* daytime
server */

15 Bind(listenfd, (SA *) &servaddr,


sizeof(servaddr));

16 Listen (listenfd, LISTENQ);

17 for ( ; ; ) {
18 connfd = Accept(listenfd, (SA *) NULL,
NULL);

19 ticks = time(NULL);
20 snprintf(buff, sizeof(buff), “%.24s\r\n”,
ctime(&ticks));
21 Write(connfd, buff, strlen(buff));

22 Close(connfd);
23 }
24 }
Intro/daytimetcpsrv.c

Anda mungkin juga menyukai