Soket Unix - Panduan Cepat
Soket memungkinkan komunikasi antara dua proses yang berbeda pada mesin yang sama atau berbeda. Lebih tepatnya, ini adalah cara untuk berbicara dengan komputer lain menggunakan deskriptor file Unix standar. Di Unix, setiap tindakan I / O dilakukan dengan menulis atau membaca deskriptor file. Deskriptor file hanyalah bilangan bulat yang terkait dengan file yang terbuka dan bisa berupa koneksi jaringan, file teks, terminal, atau yang lainnya.
Bagi seorang programmer, soket terlihat dan berperilaku seperti deskriptor file tingkat rendah. Ini karena perintah seperti read () dan write () bekerja dengan soket dengan cara yang sama seperti pada file dan pipa.
Soket pertama kali diperkenalkan di 2.1BSD dan kemudian disempurnakan menjadi bentuk saat ini dengan 4.2BSD. Fitur soket sekarang tersedia dengan rilis sistem UNIX terbaru.
Dimana Socket Digunakan?
Soket Unix digunakan dalam kerangka aplikasi klien-server. Server adalah proses yang melakukan beberapa fungsi berdasarkan permintaan dari klien. Sebagian besar protokol tingkat aplikasi seperti FTP, SMTP, dan POP3 menggunakan soket untuk membuat koneksi antara klien dan server dan kemudian untuk bertukar data.
Jenis Socket
Ada empat jenis soket yang tersedia untuk pengguna. Dua yang pertama paling sering digunakan dan dua yang terakhir jarang digunakan.
Proses dianggap berkomunikasi hanya antara soket dengan jenis yang sama tetapi tidak ada batasan yang mencegah komunikasi antara soket jenis yang berbeda.
Stream Sockets- Pengiriman dalam lingkungan jaringan dijamin. Jika Anda mengirim melalui soket aliran tiga item "A, B, C", mereka akan tiba dalam urutan yang sama - "A, B, C". Soket ini menggunakan TCP (Transmission Control Protocol) untuk transmisi data. Jika pengiriman tidak memungkinkan, pengirim menerima indikator kesalahan. Rekaman data tidak memiliki batasan apapun.
Datagram Sockets- Pengiriman dalam lingkungan jaringan tidak dijamin. Mereka tidak memiliki koneksi karena Anda tidak perlu memiliki koneksi terbuka seperti di Stream Sockets - Anda membuat paket dengan informasi tujuan dan mengirimkannya. Mereka menggunakan UDP (User Datagram Protocol).
Raw Sockets- Ini memberi pengguna akses ke protokol komunikasi yang mendasarinya, yang mendukung abstraksi soket. Soket ini biasanya berorientasi pada datagram, meskipun karakteristik pastinya bergantung pada antarmuka yang disediakan oleh protokol. Soket mentah tidak ditujukan untuk pengguna umum; mereka telah disediakan terutama bagi mereka yang tertarik dalam mengembangkan protokol komunikasi baru, atau untuk mendapatkan akses ke beberapa fasilitas yang lebih samar dari protokol yang ada.
Sequenced Packet Sockets- Mereka mirip dengan soket aliran, dengan pengecualian bahwa batas rekaman dipertahankan. Antarmuka ini disediakan hanya sebagai bagian dari abstraksi soket Sistem Jaringan (NS), dan sangat penting dalam sebagian besar aplikasi NS yang serius. Soket paket berurutan memungkinkan pengguna untuk memanipulasi header Sequence Packet Protocol (SPP) atau Internet Datagram Protocol (IDP) pada paket atau sekelompok paket, baik dengan menulis header prototipe bersama dengan data apa pun yang akan dikirim, atau dengan menentukan header default untuk digunakan dengan semua data keluar, dan memungkinkan pengguna menerima header pada paket masuk.
Apa selanjutnya?
Beberapa bab berikutnya dimaksudkan untuk memperkuat dasar-dasar Anda dan mempersiapkan landasan sebelum Anda dapat menulis program Server dan Klien menggunakan socket . Jika Anda ingin langsung melompat untuk melihat cara menulis program klien dan server, maka Anda dapat melakukannya tetapi tidak disarankan. Sangat disarankan agar Anda melanjutkan langkah demi langkah dan menyelesaikan beberapa bab awal ini untuk membuat dasar Anda sebelum melanjutkan melakukan pemrograman.
Sebelum kita melanjutkan dengan hal yang sebenarnya, mari kita bahas sedikit tentang Alamat Jaringan - Alamat IP.
Alamat host IP, atau lebih umum hanya alamat IP, digunakan untuk mengidentifikasi host yang terhubung ke Internet. IP adalah singkatan dari Internet Protocol dan mengacu pada Lapisan Internet dari keseluruhan arsitektur jaringan Internet.
Alamat IP adalah kuantitas 32-bit yang ditafsirkan sebagai empat angka atau oktet 8-bit. Setiap alamat IP secara unik mengidentifikasi jaringan pengguna yang berpartisipasi, host di jaringan, dan kelas jaringan pengguna.
Alamat IP biasanya ditulis dalam notasi desimal bertitik dalam bentuk N1.N2.N3.N4, di mana setiap Ni adalah angka desimal antara 0 dan 255 desimal (00 hingga FF heksadesimal).
Kelas Alamat
Alamat IP dikelola dan dibuat oleh Internet Assigned Numbers Authority (IANA). Ada lima kelas alamat yang berbeda. Anda dapat menentukan di kelas mana alamat IP berada dengan memeriksa empat bit pertama dari alamat IP.
Class A alamat dimulai dengan 0xxx, atau 1 to 126 desimal.
Class B alamat dimulai dengan 10xx, atau 128 to 191 desimal.
Class C alamat dimulai dengan 110x, atau 192 to 223 desimal.
Class D alamat dimulai dengan 1110, atau 224 to 239 desimal.
Class E alamat dimulai dengan 1111, atau 240 to 254 desimal.
Alamat dimulai dengan 01111111, atau 127 desimal, dicadangkan untuk loopback dan untuk pengujian internal pada mesin lokal [Anda dapat menguji ini: Anda harus selalu dapat melakukan ping 127.0.0.1, yang menunjuk pada diri Anda sendiri]; Alamat Kelas D dicadangkan untuk multicasting; Alamat Kelas E dicadangkan untuk penggunaan di masa mendatang. Mereka tidak boleh digunakan untuk alamat host.
Contoh
Class | Leftmost bits | Start address | Finish address |
SEBUAH | 0xxx | 0.0.0.0 | 127.255.255.255 |
B | 10xx | 128.0.0.0 | 191.255.255.255 |
C | 110x | 192.0.0.0 | 223.255.255.255 |
D | 1110 | 224.0.0.0 | 239.255.255.255 |
E | 1111 | 240.0.0.0 | 255.255.255.255 |
Subnetting
Subnetting atau subnetworking pada dasarnya berarti bercabang dari jaringan. Ini dapat dilakukan karena berbagai alasan seperti jaringan dalam suatu organisasi, penggunaan media fisik yang berbeda (seperti Ethernet, FDDI, WAN, dll.), Pemeliharaan ruang alamat, dan keamanan. Alasan paling umum adalah untuk mengontrol lalu lintas jaringan.
Ide dasar dalam pembuatan subnet adalah untuk mempartisi bagian pengenal host dari alamat IP menjadi dua bagian -
- Alamat subnet dalam alamat jaringan itu sendiri; dan
- Alamat host di subnet.
Misalnya, format alamat Kelas B yang umum adalah N1.N2.SH, di mana N1.N2 mengidentifikasi jaringan Kelas B, bidang 8-bit S mengidentifikasi subnet, dan bidang 8-bit H mengidentifikasi host di subnet.
Nama host dalam hal angka sulit untuk diingat dan karenanya disebut dengan nama biasa seperti Takshila atau Nalanda. Kami menulis aplikasi perangkat lunak untuk mengetahui alamat IP bertitik yang sesuai dengan nama yang diberikan.
Proses menemukan alamat IP bertitik berdasarkan nama host alfanumerik yang diberikan dikenal sebagai hostname resolution.
Resolusi nama host dilakukan oleh perangkat lunak khusus yang berada pada sistem berkapasitas tinggi. Sistem ini disebut Domain Name Systems (DNS), yang menyimpan pemetaan alamat IP dan nama biasa yang sesuai.
File / etc / hosts
Korespondensi antara nama host dan alamat IP disimpan dalam file bernama host . Di sebagian besar sistem, file ini ditemukan di/etc direktori.
Entri dalam file ini terlihat seperti berikut -
# This represents a comments in /etc/hosts file.
127.0.0.1 localhost
192.217.44.207 nalanda metro
153.110.31.18 netserve
153.110.31.19 mainserver centeral
153.110.31.20 samsonite
64.202.167.10 ns3.secureserver.net
64.202.167.97 ns4.secureserver.net
66.249.89.104 www.google.com
68.178.157.132 services.amrood.com
Perhatikan bahwa lebih dari satu nama dapat dikaitkan dengan alamat IP tertentu. File ini digunakan saat mengkonversi dari alamat IP ke nama host dan sebaliknya.
Anda tidak akan memiliki akses untuk mengedit file ini, jadi jika Anda ingin memasukkan nama host apa pun bersama dengan alamat IP, Anda harus memiliki izin root.
Sebagian besar Aplikasi Net menggunakan arsitektur Client-Server, yang mengacu pada dua proses atau dua aplikasi yang berkomunikasi satu sama lain untuk bertukar beberapa informasi. Salah satu dari dua proses bertindak sebagai proses klien, dan proses lainnya bertindak sebagai server.
Proses Klien
Ini adalah proses yang biasanya membuat permintaan informasi. Setelah mendapatkan respon, proses ini dapat menghentikan atau melakukan beberapa pemrosesan lainnya.
Example, Browser Internet berfungsi sebagai aplikasi klien, yang mengirimkan permintaan ke Server Web untuk mendapatkan satu halaman web HTML.
Proses Server
Ini adalah proses yang menerima permintaan dari klien. Setelah mendapatkan permintaan dari klien, proses ini akan melakukan pemrosesan yang diperlukan, mengumpulkan informasi yang diminta, dan mengirimkannya ke klien pemohon. Setelah selesai, itu siap untuk melayani klien lain. Proses server selalu waspada dan siap melayani permintaan yang masuk.
Example - Server Web terus menunggu permintaan dari Browser Internet dan segera setelah mendapat permintaan dari browser, ia mengambil halaman HTML yang diminta dan mengirimkannya kembali ke Browser itu.
Perhatikan bahwa klien perlu mengetahui alamat server, tetapi server tidak perlu mengetahui alamat atau bahkan keberadaan klien sebelum sambungan dibuat. Setelah koneksi dibuat, kedua belah pihak dapat mengirim dan menerima informasi.
Arsitektur 2 tingkat dan 3 tingkat
Ada dua jenis arsitektur klien-server -
2-tier architecture- Dalam arsitektur ini, klien berinteraksi langsung dengan server. Jenis arsitektur ini mungkin memiliki beberapa lubang keamanan dan masalah kinerja. Internet Explorer dan Web Server bekerja pada arsitektur dua tingkat. Di sini masalah keamanan diselesaikan menggunakan Secure Socket Layer (SSL).
3-tier architectures- Dalam arsitektur ini, satu perangkat lunak lagi berada di antara klien dan server. Perangkat lunak tengah ini disebut 'middleware'. Middleware digunakan untuk melakukan semua pemeriksaan keamanan dan load balancing jika terjadi beban berat. Middleware mengambil semua permintaan dari klien dan setelah melakukan otentikasi yang diperlukan, ia meneruskan permintaan itu ke server. Kemudian server melakukan pemrosesan yang diperlukan dan mengirimkan respons kembali ke middleware dan akhirnya middleware meneruskan respons ini kembali ke klien. Jika Anda ingin mengimplementasikan arsitektur 3-tier, maka Anda dapat menyimpan middleware seperti Web Logic atau perangkat lunak WebSphere di antara Server Web dan Browser Web Anda.
Jenis Server
Ada dua jenis server yang dapat Anda miliki -
Iterative Server- Ini adalah bentuk server paling sederhana di mana proses server melayani satu klien dan setelah menyelesaikan permintaan pertama, dibutuhkan permintaan dari klien lain. Sementara itu, klien lain terus menunggu.
Concurrent Servers- Jenis server ini menjalankan beberapa proses bersamaan untuk melayani banyak permintaan dalam satu waktu karena satu proses mungkin membutuhkan waktu lebih lama dan klien lain tidak bisa menunggu begitu lama. Cara termudah untuk menulis server bersamaan di bawah Unix adalah dengan membagi proses anak untuk menangani setiap klien secara terpisah.
Bagaimana Membuat Klien
Panggilan sistem untuk membuat koneksi agak berbeda untuk klien dan server, tetapi keduanya melibatkan konstruksi dasar soket. Kedua proses membuat soketnya sendiri.
Langkah-langkah yang terlibat dalam membangun soket di sisi klien adalah sebagai berikut -
Buat soket dengan socket() panggilan sistem.
Hubungkan soket ke alamat server menggunakan connect() panggilan sistem.
Mengirim dan menerima data. Ada beberapa cara untuk melakukan ini, tetapi cara paling sederhana adalah dengan menggunakanread() dan write() panggilan sistem.
Cara membuat Server
Langkah-langkah yang terlibat dalam membuat soket di sisi server adalah sebagai berikut -
Buat soket dengan socket() panggilan sistem.
Ikat soket ke alamat menggunakan bind()panggilan sistem. Untuk soket server di Internet, alamat terdiri dari nomor port pada mesin host.
Dengarkan koneksi dengan listen() panggilan sistem.
Terima koneksi dengan accept()panggilan sistem. Panggilan ini biasanya memblokir koneksi hingga klien terhubung dengan server.
Mengirim dan menerima data menggunakan read() dan write() panggilan sistem.
Interaksi Klien dan Server
Berikut adalah diagram yang menunjukkan interaksi Klien dan Server lengkap -
Berbagai struktur digunakan dalam Unix Socket Programming untuk menyimpan informasi tentang alamat dan port, dan informasi lainnya. Sebagian besar fungsi soket memerlukan penunjuk ke struktur alamat soket sebagai argumen. Struktur yang didefinisikan dalam bab ini terkait dengan Keluarga Protokol Internet.
sockaddr
Struktur pertama adalah sockaddr yang menyimpan informasi soket -
struct sockaddr {
unsigned short sa_family;
char sa_data[14];
};
Ini adalah struktur alamat soket umum, yang akan diteruskan di sebagian besar panggilan fungsi soket. Tabel berikut memberikan deskripsi bidang anggota -
Atribut | Nilai | Deskripsi |
---|---|---|
sa_family | AF_INET AF_UNIX AF_NS AF_IMPLINK |
Ini mewakili keluarga alamat. Di sebagian besar aplikasi berbasis Internet, kami menggunakan AF_INET. |
sa_data | Alamat khusus protokol | Isi dari 14 byte alamat spesifik protokol diinterpretasikan menurut jenis alamat. Untuk keluarga Internet, kami akan menggunakan alamat IP nomor port, yang diwakili oleh struktur sockaddr_in yang ditentukan di bawah. |
sockaddr in
Struktur kedua yang membantu Anda mengacu pada elemen soket adalah sebagai berikut -
struct sockaddr_in {
short int sin_family;
unsigned short int sin_port;
struct in_addr sin_addr;
unsigned char sin_zero[8];
};
Berikut adalah deskripsi bidang anggota -
Atribut | Nilai | Deskripsi |
---|---|---|
sa_family | AF_INET AF_UNIX AF_NS AF_IMPLINK |
Ini mewakili keluarga alamat. Di sebagian besar aplikasi berbasis Internet, kami menggunakan AF_INET. |
sin_port | Service Port | Nomor port 16-bit di Network Byte Order. |
sin_addr | Alamat IP | Alamat IP 32-bit di Network Byte Order. |
sin_zero | Tidak digunakan | Anda baru saja menyetel nilai ini ke NULL karena ini tidak digunakan. |
di addr
Struktur ini hanya digunakan pada struktur di atas sebagai bidang struktur dan menampung 32 bit netid / hostid.
struct in_addr {
unsigned long s_addr;
};
Berikut adalah deskripsi bidang anggota -
Atribut | Nilai | Deskripsi |
---|---|---|
s_addr | pelabuhan layanan | Alamat IP 32-bit di Network Byte Order. |
tuan rumah
Struktur ini digunakan untuk menyimpan informasi yang berhubungan dengan host.
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list
#define h_addr h_addr_list[0]
};
Berikut adalah deskripsi bidang anggota -
Atribut | Nilai | Deskripsi |
---|---|---|
h_name | ti.com dll. | Itu adalah nama resmi tuan rumah. Misalnya, tutorialspoint.com, google.com, dll. |
h_aliases | TI | Ini memegang daftar alias nama host. |
h_addrtype | AF_INET | Ini berisi keluarga alamat dan dalam kasus aplikasi berbasis Internet, itu akan selalu AF_INET. |
h_length | 4 | Ini memegang panjang alamat IP, yaitu 4 untuk Alamat Internet. |
h_addr_list | in_addr | Untuk alamat Internet, array pointer h_addr_list [0], h_addr_list [1], dan seterusnya, adalah poin ke struktur in_addr. |
NOTE - h_addr didefinisikan sebagai h_addr_list [0] untuk menjaga kompatibilitas ke belakang.
hamba
Struktur khusus ini digunakan untuk menyimpan informasi yang terkait dengan layanan dan port terkait.
struct servent {
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
};
Berikut adalah deskripsi bidang anggota -
Atribut | Nilai | Deskripsi |
---|---|---|
nama S | http | Ini adalah nama resmi layanan tersebut. Misalnya SMTP, FTP POP3, dll. |
s_aliases | ALIAS | Ini memegang daftar alias layanan. Sebagian besar waktu ini akan disetel ke NULL. |
olahraga | 80 | Ini akan memiliki nomor port terkait. Misalnya, untuk HTTP, nilainya menjadi 80. |
s_proto | TCP UDP |
Ini diatur ke protokol yang digunakan. Layanan Internet disediakan menggunakan TCP atau UDP. |
Tip tentang Struktur Socket
Struktur alamat soket merupakan bagian integral dari setiap program jaringan. Kami mengalokasikannya, mengisinya, dan meneruskan pointer ke berbagai fungsi soket. Kadang-kadang kita melewatkan pointer ke salah satu struktur ini ke fungsi soket dan mengisi isinya.
Kami selalu melewatkan struktur ini dengan referensi (yaitu, kami mengirimkan pointer ke struktur, bukan struktur itu sendiri), dan kami selalu meneruskan ukuran struktur sebagai argumen lain.
Ketika fungsi soket mengisi suatu struktur, panjangnya juga dilewatkan oleh referensi, sehingga nilainya dapat diperbarui oleh fungsi tersebut. Kami menyebut argumen hasil nilai ini.
Selalu, setel variabel struktur ke NULL (yaitu, '\ 0') dengan menggunakan fungsi memset () untuk bzero (), jika tidak maka akan mendapatkan nilai sampah yang tidak diharapkan dalam struktur Anda.
Ketika proses klien ingin menghubungkan server, klien harus memiliki cara untuk mengidentifikasi server yang ingin dihubungkan. Jika klien mengetahui alamat Internet 32-bit dari host tempat server berada, klien dapat menghubungi host tersebut. Tetapi bagaimana klien mengidentifikasi proses server tertentu yang berjalan pada host itu?
Untuk mengatasi masalah mengidentifikasi proses server tertentu yang berjalan di host, baik TCP dan UDP telah menetapkan sekelompok port yang terkenal.
Untuk tujuan kami, port akan didefinisikan sebagai bilangan bulat antara 1024 dan 65535. Ini karena semua nomor port yang lebih kecil dari 1024 dianggap terkenal - misalnya, telnet menggunakan port 23, http menggunakan 80, ftp menggunakan 21, dan seterusnya.
Penetapan port ke layanan jaringan dapat ditemukan di file / etc / services. Jika Anda menulis server Anda sendiri, maka harus berhati-hati dalam menetapkan port ke server Anda. Anda harus memastikan bahwa port ini tidak boleh ditetapkan ke server lain.
Biasanya merupakan praktik untuk menetapkan nomor port lebih dari 5000. Tetapi ada banyak organisasi yang telah menulis server dengan nomor port lebih dari 5000. Misalnya, Yahoo Messenger berjalan pada 5050, SIP Server berjalan pada 5060, dll.
Contoh Pelabuhan dan Layanan
Berikut adalah daftar kecil layanan dan port terkait. Anda dapat menemukan daftar terbaru dari port internet dan layanan terkait di IANA - TCP / IP Port Assignments .
Service | Port Number | Service Description |
gema | 7 | UDP / TCP mengirimkan kembali apa yang diterimanya. |
membuang | 9 | UDP / TCP membuang input. |
siang hari | 13 | UDP / TCP mengembalikan waktu ASCII. |
Chargen | 19 | UDP / TCP mengembalikan karakter. |
ftp | 21 | Transfer file TCP. |
telnet | 23 | Login jarak jauh TCP. |
smtp | 25 | Email TCP. |
siang hari | 37 | UDP / TCP mengembalikan waktu biner. |
tftp | 69 | Transfer file UDP sepele. |
jari | 79 | Info TCP pada pengguna. |
http | 80 | TCP World Wide Web. |
Gabung | 513 | Login jarak jauh TCP. |
WHO | 513 | Info UDP berbeda pada pengguna. |
Xserver | 6000 | Jendela TCP X (NB> 1023). |
Fungsi Pelabuhan dan Layanan
Unix menyediakan fungsi berikut untuk mengambil nama layanan dari file / etc / services.
struct servent *getservbyname(char *name, char *proto) - Panggilan ini mengambil nama layanan dan nama protokol, dan mengembalikan nomor port yang sesuai untuk layanan itu.
struct servent *getservbyport(int port, char *proto) - Panggilan ini menggunakan nomor port dan nama protokol, dan mengembalikan nama layanan yang sesuai.
Nilai yang dikembalikan untuk setiap fungsi adalah penunjuk ke struktur dengan bentuk berikut -
struct servent {
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
};
Berikut adalah deskripsi bidang anggota -
Atribut | Nilai | Deskripsi |
---|---|---|
nama S | http | Itu adalah nama resmi layanan tersebut. Misalnya SMTP, FTP POP3, dll. |
s_aliases | ALIAS | Ini memegang daftar alias layanan. Biasanya, ini akan disetel ke NULL. |
olahraga | 80 | Ini akan memiliki nomor port terkait. Misalnya, untuk HTTP, nilainya menjadi 80. |
s_proto | TCP UDP |
Ini diatur ke protokol yang digunakan. Layanan Internet disediakan menggunakan TCP atau UDP. |
Sayangnya, tidak semua komputer menyimpan byte yang terdiri dari nilai multibyte dalam urutan yang sama. Pertimbangkan internet 16-bit yang terdiri dari 2 byte. Ada dua cara untuk menyimpan nilai ini.
Little Endian - Dalam skema ini, byte orde rendah disimpan di alamat awal (A) dan byte orde tinggi disimpan di alamat berikutnya (A + 1).
Big Endian - Dalam skema ini, byte orde tinggi disimpan di alamat awal (A) dan byte orde rendah disimpan di alamat berikutnya (A + 1).
Untuk mengizinkan mesin dengan konvensi urutan byte yang berbeda berkomunikasi satu sama lain, protokol Internet menetapkan konvensi urutan byte kanonik untuk data yang dikirim melalui jaringan. Ini dikenal sebagai Network Byte Order.
Saat membuat sambungan soket Internet, Anda harus memastikan bahwa data dalam anggota sin_port dan sin_addr struktur sockaddr_in terwakili dalam Urutan Byte Jaringan.
Fungsi Pengurutan Byte
Rutinitas untuk mengkonversi data antara representasi internal host dan Network Byte Order adalah sebagai berikut -
Fungsi | Deskripsi |
---|---|
htons () | Host ke Jaringan Pendek |
htonl () | Host ke Jaringan Panjang |
ntohl () | Jaringan untuk Host Long |
ntohs () | Jaringan ke Host Pendek |
Di bawah ini adalah beberapa detail lebih lanjut tentang fungsi-fungsi ini -
unsigned short htons(unsigned short hostshort) - Fungsi ini mengubah jumlah 16-bit (2-byte) dari urutan byte host ke urutan byte jaringan.
unsigned long htonl(unsigned long hostlong) - Fungsi ini mengubah jumlah 32-bit (4-byte) dari urutan byte host ke urutan byte jaringan.
unsigned short ntohs(unsigned short netshort) - Fungsi ini mengubah jumlah 16-bit (2-byte) dari urutan byte jaringan menjadi urutan byte host.
unsigned long ntohl(unsigned long netlong) - Fungsi ini mengubah jumlah 32-bit dari urutan byte jaringan menjadi urutan byte host.
Fungsi ini adalah makro dan menghasilkan penyisipan kode sumber konversi ke dalam program pemanggil. Pada mesin little-endian, kode akan mengubah nilai di sekitar urutan byte jaringan. Pada mesin big-endian, tidak ada kode yang dimasukkan karena tidak diperlukan; fungsi didefinisikan sebagai null.
Program untuk Menentukan Urutan Host Byte
Simpan kode berikut dalam file byteorder.c dan kemudian kompilasi dan jalankan melalui mesin Anda.
Dalam contoh ini, kami menyimpan nilai dua byte 0x0102 dalam bilangan bulat pendek dan kemudian melihat dua byte berturut-turut, c [0] (alamat A) dan c [1] (alamat A + 1) untuk menentukan byte memesan.
#include <stdio.h>
int main(int argc, char **argv) {
union {
short s;
char c[sizeof(short)];
}un;
un.s = 0x0102;
if (sizeof(short) == 2) {
if (un.c[0] == 1 && un.c[1] == 2)
printf("big-endian\n");
else if (un.c[0] == 2 && un.c[1] == 1)
printf("little-endian\n");
else
printf("unknown\n");
}
else {
printf("sizeof(short) = %d\n", sizeof(short));
}
exit(0);
}
Output yang dihasilkan oleh program ini pada mesin Pentium adalah sebagai berikut -
$> gcc byteorder.c $> ./a.out
little-endian
$>
Unix menyediakan berbagai panggilan fungsi untuk membantu Anda memanipulasi alamat IP. Fungsi-fungsi ini mengubah alamat Internet antara string ASCII (apa yang lebih disukai manusia) dan nilai biner urutan byte jaringan (nilai yang disimpan dalam struktur alamat soket).
Tiga panggilan fungsi berikut digunakan untuk pengalamatan IPv4 -
- int inet_aton (const char * strptr, struct in_addr * addrptr)
- in_addr_t inet_addr (const char * strptr)
- char * inet_ntoa (struct in_addr inaddr)
int inet_aton (const char * strptr, struct in_addr * addrptr)
Panggilan fungsi ini mengubah string yang ditentukan dalam notasi titik standar Internet ke alamat jaringan, dan menyimpan alamat dalam struktur yang disediakan. Alamat yang diubah akan berada dalam Network Byte Order (byte diurutkan dari kiri ke kanan). Ia mengembalikan 1 jika string itu valid dan 0 pada kesalahan.
Berikut adalah contoh penggunaan -
#include <arpa/inet.h>
(...)
int retval;
struct in_addr addrptr
memset(&addrptr, '\0', sizeof(addrptr));
retval = inet_aton("68.178.157.132", &addrptr);
(...)
in_addr_t inet_addr (const char * strptr)
Panggilan fungsi ini mengubah string yang ditentukan dalam notasi titik standar Internet menjadi nilai integer yang cocok untuk digunakan sebagai alamat Internet. Alamat yang diubah akan berada dalam Network Byte Order (byte diurutkan dari kiri ke kanan). Ia mengembalikan byte jaringan biner 32-bit memerintahkan alamat IPv4 dan INADDR_NONE pada kesalahan.
Berikut adalah contoh penggunaan -
#include <arpa/inet.h>
(...)
struct sockaddr_in dest;
memset(&dest, '\0', sizeof(dest));
dest.sin_addr.s_addr = inet_addr("68.178.157.132");
(...)
char * inet_ntoa (struct in_addr inaddr)
Panggilan fungsi ini mengubah alamat host Internet yang ditentukan menjadi string dalam notasi titik standar Internet.
Berikut adalah contoh penggunaan -
#include <arpa/inet.h>
(...)
char *ip;
ip = inet_ntoa(dest.sin_addr);
printf("IP Address is: %s\n",ip);
(...)
Bab ini menjelaskan fungsi soket inti yang diperlukan untuk menulis klien dan server TCP lengkap.
Diagram berikut menunjukkan interaksi Klien dan Server lengkap -
Fungsi soket
Untuk melakukan I / O jaringan, hal pertama yang harus dilakukan oleh suatu proses adalah memanggil fungsi soket, menentukan jenis protokol komunikasi yang diinginkan dan keluarga protokol, dll.
#include <sys/types.h>
#include <sys/socket.h>
int socket (int family, int type, int protocol);
Panggilan ini mengembalikan deskriptor soket yang dapat Anda gunakan di panggilan sistem nanti atau -1 pada kesalahan.
Parameter
family - Ini menentukan keluarga protokol dan merupakan salah satu konstanta yang ditunjukkan di bawah ini -
Keluarga | Deskripsi |
---|---|
AF_INET | Protokol IPv4 |
AF_INET6 | Protokol IPv6 |
AF_LOCAL | Protokol domain Unix |
AF_ROUTE | Soket Perutean |
AF_KEY | Soket Ket |
Bab ini tidak membahas protokol lain kecuali IPv4.
type- Ini menentukan jenis soket yang Anda inginkan. Ini dapat mengambil salah satu dari nilai berikut -
Tipe | Deskripsi |
---|---|
SOCK_STREAM | Soket aliran |
SOCK_DGRAM | Soket datagram |
SOCK_SEQPACKET | Soket paket berurutan |
SOCK_RAW | Soket mentah |
protocol - Argumen harus disetel ke jenis protokol tertentu yang diberikan di bawah ini, atau 0 untuk memilih default sistem untuk kombinasi keluarga dan jenis yang diberikan -
Protokol | Deskripsi |
---|---|
IPPROTO_TCP | Protokol transport TCP |
IPPROTO_UDP | Protokol transportasi UDP |
IPPROTO_SCTP | Protokol transport SCTP |
The connect Fungsi
Fungsi menghubungkan digunakan oleh klien TCP untuk membuat sambungan dengan server TCP.
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
Panggilan ini mengembalikan 0 jika berhasil terhubung ke server, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
serv_addr - Ini adalah penunjuk ke struct sockaddr yang berisi alamat IP tujuan dan port.
addrlen - Setel ke sizeof (struct sockaddr).
The mengikat Fungsi
Fungsi bind memberikan alamat protokol lokal ke soket. Dengan protokol Internet, alamat protokol adalah kombinasi dari alamat IPv4 32-bit atau alamat IPv6 128-bit, bersama dengan nomor port TCP atau UDP 16-bit. Fungsi ini hanya dipanggil oleh server TCP.
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr,int addrlen);
Panggilan ini mengembalikan 0 jika berhasil mengikat ke alamat, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
my_addr - Ini adalah penunjuk ke struct sockaddr yang berisi alamat IP lokal dan port.
addrlen - Setel ke sizeof (struct sockaddr).
Anda dapat memasukkan alamat IP dan port Anda secara otomatis
Nilai 0 untuk nomor port berarti sistem akan memilih port acak, dan nilai INADDR_ANY untuk alamat IP berarti alamat IP server akan ditetapkan secara otomatis.
server.sin_port = 0;
server.sin_addr.s_addr = INADDR_ANY;
NOTE- Semua port di bawah 1024 sudah dipesan. Anda dapat mengatur port di atas 1024 dan di bawah 65535 kecuali port tersebut digunakan oleh program lain.
The mendengarkan Fungsi
Fungsi mendengarkan hanya dipanggil oleh server TCP dan melakukan dua tindakan -
Fungsi mendengarkan mengubah soket yang tidak terhubung menjadi soket pasif, yang menunjukkan bahwa kernel harus menerima permintaan koneksi masuk yang diarahkan ke soket ini.
Argumen kedua untuk fungsi ini menentukan jumlah maksimum koneksi yang harus antri kernel untuk soket ini.
#include <sys/types.h>
#include <sys/socket.h>
int listen(int sockfd,int backlog);
Panggilan ini mengembalikan 0 jika berhasil, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
backlog - Ini adalah jumlah koneksi yang diizinkan.
The menerima Fungsi
Fungsi terima dipanggil oleh server TCP untuk mengembalikan koneksi selesai berikutnya dari depan antrian koneksi yang sudah selesai. Tanda tangan panggilan tersebut adalah sebagai berikut -
#include <sys/types.h>
#include <sys/socket.h>
int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
Panggilan ini mengembalikan deskriptor non-negatif tentang sukses, jika tidak maka akan mengembalikan -1 pada kesalahan. Deskriptor yang dikembalikan diasumsikan sebagai deskriptor soket klien dan semua operasi baca-tulis akan dilakukan pada deskriptor ini untuk berkomunikasi dengan klien.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
cliaddr - Ini adalah penunjuk ke struct sockaddr yang berisi alamat IP dan port klien.
addrlen - Setel ke sizeof (struct sockaddr).
The kirim Fungsi
Fungsi kirim digunakan untuk mengirim data melalui soket aliran atau soket datagram TERHUBUNG. Jika Anda ingin mengirim data melalui soket datagram TIDAK TERSAMBUNG, Anda harus menggunakan fungsi sendto ().
Anda dapat menggunakan panggilan sistem write () untuk mengirim data. Tanda tangannya adalah sebagai berikut -
int send(int sockfd, const void *msg, int len, int flags);
Panggilan ini mengembalikan jumlah byte yang dikirim, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
msg - Ini adalah penunjuk ke data yang ingin Anda kirim.
len - Ini adalah panjang data yang ingin Anda kirim (dalam byte).
flags - Sudah disetel ke 0.
The recv Fungsi
Fungsi recv digunakan untuk menerima data melalui soket aliran atau soket datagram TERHUBUNG. Jika Anda ingin menerima data melalui soket datagram TIDAK TERSAMBUNG Anda harus menggunakan recvfrom ().
Anda dapat menggunakan panggilan sistem read () untuk membaca data. Panggilan ini dijelaskan di bab fungsi pembantu.
int recv(int sockfd, void *buf, int len, unsigned int flags);
Panggilan ini mengembalikan jumlah byte yang dibaca ke dalam buffer, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
buf - Ini adalah buffer untuk membaca informasi.
len - Ini adalah panjang maksimum buffer.
flags - Sudah disetel ke 0.
The sendto Fungsi
Fungsi sendto digunakan untuk mengirim data melalui soket datagram TIDAK TERSAMBUNG. Tanda tangannya adalah sebagai berikut -
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
Panggilan ini mengembalikan jumlah byte yang dikirim, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
msg - Ini adalah penunjuk ke data yang ingin Anda kirim.
len - Ini adalah panjang data yang ingin Anda kirim (dalam byte).
flags - Sudah disetel ke 0.
to - Ini adalah penunjuk ke struct sockaddr untuk host tempat data harus dikirim.
tolen - Sudah disetel ke sizeof (struct sockaddr).
The recvfrom Fungsi
Fungsi recvfrom digunakan untuk menerima data dari soket datagram UNCONNECTED.
int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);
Panggilan ini mengembalikan jumlah byte yang dibaca ke buffer, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
buf - Ini adalah buffer untuk membaca informasi.
len - Ini adalah panjang maksimum buffer.
flags - Sudah disetel ke 0.
from - Ini adalah penunjuk ke struct sockaddr untuk host tempat data harus dibaca.
fromlen - Sudah disetel ke sizeof (struct sockaddr).
The dekat Fungsi
Fungsi close digunakan untuk menutup komunikasi antara klien dan server. Sintaksnya adalah sebagai berikut -
int close( int sockfd );
Panggilan ini mengembalikan 0 jika berhasil, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
The Shutdown Fungsi
Fungsi shutdown digunakan untuk menutup komunikasi antara klien dan server dengan baik. Fungsi ini memberikan lebih banyak kontrol dibandingkan dengan fungsi tutup . Diberikan di bawah ini adalah sintaks shutdown -
int shutdown(int sockfd, int how);
Panggilan ini mengembalikan 0 jika berhasil, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
sockfd - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
how - Masukkan salah satu angkanya -
0 - menunjukkan bahwa menerima tidak diperbolehkan,
1 - menunjukkan bahwa pengiriman tidak diperbolehkan, dan
2- menunjukkan bahwa pengiriman dan penerimaan tidak diperbolehkan. Ketika how diatur ke 2, itu sama dengan close ().
The pilih Fungsi
Fungsi pemilihan menunjukkan deskriptor file yang ditentukan mana yang siap untuk dibaca, siap untuk ditulis, atau memiliki kondisi kesalahan yang tertunda.
Ketika sebuah aplikasi memanggil recv atau recvfrom , itu diblokir sampai data tiba untuk soket itu. Sebuah aplikasi dapat melakukan pemrosesan berguna lainnya saat aliran data yang masuk kosong. Situasi lain adalah ketika aplikasi menerima data dari banyak soket.
Memanggil recv atau recvfrom pada soket yang tidak memiliki data dalam antrian inputnya mencegah penerimaan data secara langsung dari soket lain. Panggilan fungsi pemilihan memecahkan masalah ini dengan mengizinkan program untuk mengumpulkan semua pegangan soket untuk melihat apakah mereka tersedia untuk operasi pembacaan dan penulisan non-pemblokiran.
Diberikan di bawah ini adalah sintaks pilih -
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
Panggilan ini mengembalikan 0 jika berhasil, jika tidak maka akan mengembalikan -1 pada kesalahan.
Parameter
nfds- Ini menentukan kisaran deskriptor file yang akan diuji. Fungsi select () menguji deskriptor file dalam rentang 0 hingga nfds-1
readfds- Ini menunjuk ke sebuah objek berjenis fd_set yang pada input, menentukan deskriptor file yang akan diperiksa untuk siap dibaca, dan pada output, menunjukkan deskriptor file mana yang siap untuk dibaca. Bisa NULL untuk menunjukkan set kosong.
writefds- Ini menunjuk ke objek berjenis fd_set yang pada input, menentukan deskriptor file yang akan diperiksa untuk siap menulis, dan pada output, menunjukkan deskriptor file mana yang siap untuk ditulis. Bisa NULL untuk menunjukkan set kosong.
exceptfds- Ini menunjuk ke sebuah objek berjenis fd_set yang pada input, menentukan deskriptor file yang akan diperiksa untuk kondisi kesalahan yang tertunda, dan pada output menunjukkan, deskriptor file mana yang memiliki kondisi kesalahan tertunda. Bisa NULL untuk menunjukkan set kosong.
timeout- Ini menunjuk ke struct timeval yang menentukan berapa lama panggilan pilih harus mengumpulkan deskriptor untuk operasi I / O yang tersedia. Jika nilai batas waktu adalah 0, maka pemilihan akan segera kembali. Jika argumen batas waktu adalah NULL, pilih akan memblokir hingga setidaknya satu pegangan file / soket siap untuk operasi I / O yang tersedia. Jika tidak, pilih akan kembali setelah jumlah waktu dalam batas waktu telah berlalu ATAU ketika setidaknya satu deskriptor file / soket siap untuk operasi I / O.
Nilai kembali dari pilih adalah jumlah pegangan yang ditentukan dalam kumpulan deskriptor file yang siap untuk I / O. Jika batas waktu yang ditentukan oleh bidang batas waktu tercapai, pilih kembali 0. Makro berikut ada untuk memanipulasi kumpulan deskriptor file -
FD_CLR(fd, &fdset)- Menghapus bit untuk deskriptor file fd di set deskriptor file fdset.
FD_ISSET(fd, &fdset)- Mengembalikan nilai bukan nol jika bit untuk deskriptor file fd disetel dalam set deskriptor file yang ditunjukkan oleh fdset , dan 0 sebaliknya.
FD_SET(fd, &fdset) - Menetapkan bit untuk deskriptor file fd dalam set deskriptor file fdset.
FD_ZERO(&fdset) - Menginisialisasi set deskriptor file fdset agar memiliki bit nol untuk semua deskriptor file.
Perilaku makro ini tidak ditentukan jika argumen fd kurang dari 0 atau lebih besar dari atau sama dengan FD_SETSIZE.
Contoh
fd_set fds;
struct timeval tv;
/* do socket initialization etc.
tv.tv_sec = 1;
tv.tv_usec = 500000;
/* tv now represents 1.5 seconds */
FD_ZERO(&fds);
/* adds sock to the file descriptor set */
FD_SET(sock, &fds);
/* wait 1.5 seconds for any data to be read from any single socket */
select(sock+1, &fds, NULL, NULL, &tv);
if (FD_ISSET(sock, &fds)) {
recvfrom(s, buffer, buffer_len, 0, &sa, &sa_len);
/* do something */
}
else {
/* do something else */
}
Bab ini menjelaskan semua fungsi helper, yang digunakan saat melakukan pemrograman soket. Fungsi pembantu lainnya dijelaskan di bab -Ports and Services, dan Jaringan Byte Orders.
The write Fungsi
Fungsi tulis mencoba menulis byte nbyte dari buffer yang ditunjukkan oleh buf ke file yang terkait dengan deskriptor file terbuka, fildes .
Anda juga dapat menggunakan fungsi send () untuk mengirim data ke proses lain.
#include <unistd.h>
int write(int fildes, const void *buf, int nbyte);
Setelah berhasil diselesaikan, write () mengembalikan jumlah byte yang sebenarnya ditulis ke file yang terkait dengan fildes. Jumlah ini tidak pernah lebih besar dari nbyte. Jika tidak, -1 dikembalikan.
Parameter
fildes - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
buf - Ini adalah penunjuk ke data yang ingin Anda kirim.
nbyte- Ini adalah jumlah byte yang akan ditulis. Jika nbyte adalah 0, write () akan mengembalikan 0 dan tidak memiliki hasil lain jika file tersebut adalah file biasa; jika tidak, hasilnya tidak ditentukan.
The read Fungsi
Fungsi baca mencoba membaca byte nbyte dari file yang terkait dengan buffer, fildes, ke dalam buffer yang ditunjukkan oleh buf.
Anda juga bisa menggunakan fungsi recv () untuk membaca data ke proses lain.
#include <unistd.h>
int read(int fildes, const void *buf, int nbyte);
Setelah berhasil diselesaikan, write () mengembalikan jumlah byte yang sebenarnya ditulis ke file yang terkait dengan fildes. Jumlah ini tidak pernah lebih besar dari nbyte. Jika tidak, -1 dikembalikan.
Parameter
fildes - Ini adalah deskriptor soket yang dikembalikan oleh fungsi soket.
buf - Ini adalah buffer untuk membaca informasi.
nbyte - Ini adalah jumlah byte untuk dibaca.
The garpu Fungsi
Fungsi garpu membuat proses baru. Proses baru yang disebut proses anak akan menjadi salinan persis dari proses pemanggilan (proses induk). Proses anak mewarisi banyak atribut dari proses induk.
#include <sys/types.h>
#include <unistd.h>
int fork(void);
Setelah berhasil menyelesaikan, fork () mengembalikan 0 ke proses anak dan ID proses dari proses anak ke proses induk. Jika tidak -1 dikembalikan ke proses induk, tidak ada proses anak yang dibuat dan errno diatur untuk menunjukkan kesalahan.
Parameter
void - Artinya tidak diperlukan parameter.
The Bzero Fungsi
Fungsi bzero menempatkan nbyte null byte dalam string s . Fungsi ini digunakan untuk mengatur semua struktur soket dengan nilai null.
void bzero(void *s, int nbyte);
Fungsi ini tidak mengembalikan apapun.
Parameter
s- Ini menentukan string yang harus diisi dengan byte nol. Ini akan menjadi titik ke variabel struktur soket.
nbyte- Ini menentukan jumlah byte yang akan diisi dengan nilai nol. Ini akan menjadi ukuran struktur soket.
The bcmp Fungsi
Fungsi bcmp membandingkan string byte s1 terhadap string byte s2. Kedua string diasumsikan sebagai byte nbyte.
int bcmp(const void *s1, const void *s2, int nbyte);
Fungsi ini mengembalikan 0 jika kedua string identik, 1 sebaliknya. Fungsi bcmp () selalu mengembalikan 0 ketika nbyte adalah 0.
Parameter
s1 - Ini menentukan string pertama yang akan dibandingkan.
s2 - Ini menentukan string kedua yang akan dibandingkan.
nbyte - Ini menentukan jumlah byte yang akan dibandingkan.
The bcopy Fungsi
Fungsi bcopy menyalin byte nbyte dari string s1 ke string s2. String yang tumpang tindih ditangani dengan benar.
void bcopy(const void *s1, void *s2, int nbyte);
Fungsi ini tidak mengembalikan apapun.
Parameter
s1 - Ini menentukan string sumber.
s2v - Ini menentukan string tujuan.
nbyte - Ini menentukan jumlah byte yang akan disalin.
The memset Fungsi
Fungsi memset juga digunakan untuk mengatur variabel struktur dengan cara yang sama sepertibzero. Lihatlah sintaksnya, yang diberikan di bawah ini.
void *memset(void *s, int c, int nbyte);
Fungsi ini mengembalikan pointer ke batal; pada kenyataannya, penunjuk ke memori yang disetel dan Anda perlu menyesuaikannya.
Parameter
s - Ini menentukan sumber yang akan disetel.
c - Ini menentukan karakter untuk diatur di tempat nbyte.
nbyte - Ini menentukan jumlah byte yang akan diatur.
Untuk membuat proses server TCP, Anda harus mengikuti langkah-langkah yang diberikan di bawah ini -
Buat soket dengan pemanggilan sistem socket () .
Ikat soket ke alamat menggunakan panggilan sistem bind () . Untuk soket server di Internet, alamat terdiri dari nomor port pada mesin host.
Dengarkan koneksi dengan panggilan sistem listen () .
Terima koneksi dengan panggilan sistem accept () . Panggilan ini biasanya memblokir hingga klien terhubung dengan server.
Mengirim dan menerima data menggunakan panggilan sistem read () dan write () .
Sekarang mari kita letakkan langkah-langkah tersebut dalam bentuk kode sumber. Letakkan kode ini ke dalam file server.c dan kompilasi dengan kompiler gcc .
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here process will
* go in sleep mode and will wait for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
/* Accept actual connection from the client */
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* If connection is established then start communicating */
bzero(buffer,256);
n = read( newsockfd,buffer,255 );
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
/* Write a response to the client */
n = write(newsockfd,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
return 0;
}
Tangani Banyak Koneksi
Untuk memungkinkan server menangani beberapa koneksi simultan, kami membuat perubahan berikut pada kode di atas -
Letakkan pernyataan accept dan kode berikut dalam loop tak terbatas.
Setelah koneksi dibuat, panggil fork () untuk membuat proses baru.
Proses anak akan menutup sockfd dan memanggil fungsi doprocessing , meneruskan deskriptor file soket baru sebagai argumen. Ketika dua proses telah menyelesaikan percakapan mereka, seperti yang ditunjukkan oleh doprocessing () kembali, proses ini keluar begitu saja.
Proses induk menutup newsockfd . Karena semua kode ini berada dalam loop tak terbatas, ia akan kembali ke pernyataan accept untuk menunggu koneksi berikutnya.
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
void doprocessing (int sock);
int main( int argc, char *argv[] ) {
int sockfd, newsockfd, portno, clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n, pid;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here
* process will go in sleep mode and will wait
* for the incoming connection
*/
listen(sockfd,5);
clilen = sizeof(cli_addr);
while (1) {
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* Create child process */
pid = fork();
if (pid < 0) {
perror("ERROR on fork");
exit(1);
}
if (pid == 0) {
/* This is the client process */
close(sockfd);
doprocessing(newsockfd);
exit(0);
}
else {
close(newsockfd);
}
} /* end of while */
}
Urutan kode berikut menunjukkan implementasi sederhana dari fungsi doprocessing .
void doprocessing (int sock) {
int n;
char buffer[256];
bzero(buffer,256);
n = read(sock,buffer,255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n",buffer);
n = write(sock,"I got your message",18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
}
Untuk membuat proses klien TCP, Anda harus mengikuti langkah-langkah yang diberikan di bawah ini & minus;
Buat soket dengan pemanggilan sistem socket () .
Hubungkan soket ke alamat server menggunakan panggilan sistem connect () .
Mengirim dan menerima data. Ada beberapa cara untuk melakukan ini, tetapi cara termudah adalah dengan menggunakan panggilan sistem read () dan write () .
Sekarang mari kita letakkan langkah-langkah tersebut dalam bentuk kode sumber. Masukkan kode ini ke dalam fileclient.c dan mengkompilasinya dengan gcc penyusun.
Jalankan program ini dan berikan nama host dan nomor port server, untuk terhubung ke server, yang harus Anda jalankan di jendela Unix lain.
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string.h>
int main(int argc, char *argv[]) {
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
portno = atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);
/* Now connect to the server */
if (connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
exit(1);
}
/* Now ask for a message from the user, this message
* will be read by server
*/
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
/* Send message to the server */
n = write(sockfd, buffer, strlen(buffer));
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
/* Now read server response */
bzero(buffer,256);
n = read(sockfd, buffer, 255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("%s\n",buffer);
return 0;
}
Berikut adalah daftar semua fungsi yang berkaitan dengan pemrograman soket.
Fungsi Pelabuhan dan Layanan
Unix menyediakan fungsi berikut untuk mengambil nama layanan dari file / etc / services.
struct servent *getservbyname(char *name, char *proto) - Panggilan ini menggunakan nama layanan dan nama protokol dan mengembalikan nomor port yang sesuai untuk layanan itu.
struct servent *getservbyport(int port, char *proto) - Panggilan ini menggunakan nomor port dan nama protokol dan mengembalikan nama layanan yang sesuai.
Fungsi Pengurutan Byte
unsigned short htons (unsigned short hostshort) - Fungsi ini mengubah jumlah 16-bit (2-byte) dari urutan byte host ke urutan byte jaringan.
unsigned long htonl (unsigned long hostlong) - Fungsi ini mengubah jumlah 32-bit (4-byte) dari urutan byte host ke urutan byte jaringan.
unsigned short ntohs (unsigned short netshort) - Fungsi ini mengubah jumlah 16-bit (2-byte) dari urutan byte jaringan menjadi urutan byte host.
unsigned long ntohl (unsigned long netlong) - Fungsi ini mengubah jumlah 32-bit dari urutan byte jaringan menjadi urutan byte host.
Fungsi Alamat IP
int inet_aton (const char *strptr, struct in_addr *addrptr)- Panggilan fungsi ini mengubah string yang ditentukan, dalam notasi titik standar Internet, ke alamat jaringan, dan menyimpan alamat dalam struktur yang disediakan. Alamat yang diubah akan berada dalam Network Byte Order (byte diurutkan dari kiri ke kanan). Ia mengembalikan 1 jika string itu valid dan 0 pada kesalahan.
in_addr_t inet_addr (const char *strptr)- Panggilan fungsi ini mengubah string yang ditentukan, dalam notasi titik standar Internet, menjadi nilai integer yang cocok untuk digunakan sebagai alamat Internet. Alamat yang diubah akan berada dalam Network Byte Order (byte diurutkan dari kiri ke kanan). Ia mengembalikan byte jaringan biner 32-bit memerintahkan alamat IPv4 dan INADDR_NONE pada kesalahan.
char *inet_ntoa (struct in_addr inaddr) - Panggilan fungsi ini mengubah alamat host Internet yang ditentukan menjadi string dalam notasi titik standar Internet.
Fungsi Inti Soket
int socket (int family, int type, int protocol) - Panggilan ini mengembalikan deskriptor soket yang dapat Anda gunakan di panggilan sistem nanti atau memberi Anda -1 pada kesalahan.
int connect (int sockfd, struct sockaddr *serv_addr, int addrlen)- Fungsi koneksi digunakan oleh klien TCP untuk membuat koneksi dengan server TCP. Panggilan ini mengembalikan 0 jika berhasil terhubung ke server, jika tidak maka akan mengembalikan -1.
int bind(int sockfd, struct sockaddr *my_addr,int addrlen)- Fungsi bind memberikan alamat protokol lokal ke soket. Panggilan ini mengembalikan 0 jika berhasil mengikat ke alamat, jika tidak maka akan mengembalikan -1.
int listen(int sockfd, int backlog)- Fungsi mendengarkan hanya dipanggil oleh server TCP untuk mendengarkan permintaan klien. Panggilan ini mengembalikan 0 jika berhasil, jika tidak maka akan mengembalikan -1.
int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)- Fungsi terima dipanggil oleh server TCP untuk menerima permintaan klien dan untuk membuat koneksi yang sebenarnya. Panggilan ini mengembalikan deskriptor non-negatif tentang sukses, jika tidak maka akan mengembalikan -1.
int send(int sockfd, const void *msg, int len, int flags)- Fungsi kirim digunakan untuk mengirim data melalui soket aliran atau soket datagram TERHUBUNG. Panggilan ini mengembalikan jumlah byte yang dikirim, jika tidak maka akan mengembalikan -1.
int recv (int sockfd, void *buf, int len, unsigned int flags)- Fungsi recv digunakan untuk menerima data melalui soket aliran atau soket datagram TERHUBUNG. Panggilan ini mengembalikan jumlah byte yang dibaca ke buffer, jika tidak maka akan mengembalikan -1 pada kesalahan.
int sendto (int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen)- Fungsi sendto digunakan untuk mengirim data melalui soket datagram TIDAK TERSAMBUNG. Panggilan ini mengembalikan jumlah byte yang dikirim, jika tidak maka akan mengembalikan -1 pada kesalahan.
int recvfrom (int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen)- Fungsi recvfrom digunakan untuk menerima data dari soket datagram TIDAK TERSAMBUNG. Panggilan ini mengembalikan jumlah byte yang dibaca ke buffer, jika tidak maka akan mengembalikan -1 pada kesalahan.
int close (int sockfd)- Fungsi close digunakan untuk menutup komunikasi antara klien dan server. Panggilan ini mengembalikan 0 jika berhasil, jika tidak maka akan mengembalikan -1.
int shutdown (int sockfd, int how)- Fungsi shutdown digunakan untuk menutup komunikasi antara klien dan server dengan baik. Fungsi ini memberikan lebih banyak kontrol dibandingkan dengan fungsi tutup. Ini mengembalikan 0 untuk kesuksesan, -1 jika tidak.
int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) - Fungsi ini digunakan untuk membaca atau menulis banyak soket.
Fungsi Pembantu Socket
int write (int fildes, const void *buf, int nbyte)- Fungsi tulis mencoba menulis byte nbyte dari buffer yang ditunjukkan oleh buf ke file yang terkait dengan deskriptor file yang terbuka, fildes. Setelah berhasil diselesaikan, write () mengembalikan jumlah byte yang sebenarnya ditulis ke file yang terkait dengan fildes. Jumlah ini tidak pernah lebih besar dari nbyte. Jika tidak, -1 dikembalikan.
int read (int fildes, const void *buf, int nbyte)- Fungsi baca mencoba membaca byte nbyte dari file yang terkait dengan deskriptor file yang terbuka, fildes, ke dalam buffer yang ditunjukkan oleh buf. Setelah berhasil diselesaikan, write () mengembalikan jumlah byte yang sebenarnya ditulis ke file yang terkait dengan fildes. Jumlah ini tidak pernah lebih besar dari nbyte. Jika tidak, -1 dikembalikan.
int fork (void)- Fungsi garpu membuat proses baru. Proses baru, yang disebut proses anak, akan menjadi salinan persis dari proses panggilan (proses induk).
void bzero (void *s, int nbyte)- Fungsi bzero menempatkan nbyte null byte dalam string s. Fungsi ini akan digunakan untuk mengatur semua struktur soket dengan nilai null.
int bcmp (const void *s1, const void *s2, int nbyte)- Fungsi bcmp membandingkan string byte s1 terhadap string byte s2. Kedua string tersebut diasumsikan sebagai byte nbyte.
void bcopy (const void *s1, void *s2, int nbyte)- Fungsi bcopy menyalin byte nbyte dari string s1 ke string s2. String yang tumpang tindih ditangani dengan benar.
void *memset(void *s, int c, int nbyte) - Fungsi memset juga digunakan untuk mengatur variabel struktur dengan cara yang sama seperti bzero.