شنبه ۲۹ دي ۱۴۰۳
Tut24 آموزش برنامه نویسی و مجله تخصصی فناوری ورود/عضویت

آموزش جاوا - شبکه

اصطلاح برنامه‌نویسی شبکه به نوشتن برنامه‌ها اشاره دارد که در چندین دستگاه (کامپیوتر) اجرا می‌شوند و دستگاه‌ها با استفاده از یک شبکه به یکدیگر متصل هستند.

پکیج java.net در واسط‌های برنامه‌نویسی J2SE مجموعه‌ای از کلاس‌ها و رابط‌ها را ارائه می‌دهد که جزئیات ارتباطی سطح پایین را فراهم می‌کنند و به شما امکان می‌دهند تا برنامه‌هایی بنویسید که تمرکز خود را بر روی حل مشکل در دست داشته باشند.

پکیج java.net پشتیبانی از دو پروتکل شبکه رایج را فراهم می‌کند:

  • TCP − TCP مخفف Transmission Control Protocol است که ارتباط قابل اعتماد بین دو برنامه را فراهم می‌کند. معمولاً از TCP بر روی پروتکل اینترنت استفاده می‌شود که به عنوان TCP/IP شناخته می‌شود.

  • UDP − UDP مخفف User Datagram Protocol است، یک پروتکل بی‌ارتباط که امکان انتقال بسته‌های داده را بین برنامه‌ها فراهم می‌کند.

این فصل درک خوبی از دو موضوع زیر را ارائه می‌دهد −

  • برنامه‌نویسی سوکت (Socket Programming) − این مفهوم بیشترین استفاده را در شبکه‌پیمایی دارد و به طور کامل توضیح داده شده است.

  • پردازش URL (URL Processing) − این به صورت جداگانه پوشش داده می‌شود. برای یادگیری درباره پردازش URL در زبان جاوا، اینجا را کلیک کنید.

برنامه‌نویسی سوکت (Socket Programming)

سوکت‌ها مکانیزم ارتباط بین دو کامپیوتر با استفاده از TCP را فراهم می‌کنند. یک برنامه مشتری یک سوکت در نقطه پایانی ارتباط ایجاد می‌کند و سعی می‌کند آن سوکت را به سرور متصل کند.

زمانی که اتصال برقرار شود، سرور یک شی سوکت در نقطه پایانی ارتباط خود ایجاد می‌کند. حالا مشتری و سرور می‌توانند با نوشتن به سوکت و خواندن از سوکت با یکدیگر ارتباط برقرار کنند.

کلاس java.net.Socket یک سوکت را نمایندگی می‌کند و کلاس java.net.ServerSocket مکانیزمی برای برنامه سرور فراهم می‌کند تا به مشتریان گوش دهد و اتصالات را با آن‌ها برقرار کند.

مراحل زیر در برقراری اتصال TCP بین دو کامپیوتر با استفاده از سوکت رخ می‌دهند −

  • سرور یک شی ServerSocket نمونه‌سازی می‌کند و شماره پورتی که ارتباط روی آن باید انجام شود را مشخص می‌کند.

  • سرور متد accept() کلاس ServerSocket را فراخوانی می‌کند. این متد منتظر می‌ماند تا یک مشتری به سرور در پورت داده شده متصل شود.

  • پس از اینکه سرور منتظر است، مشتری یک شی Socket نمونه‌سازی می‌کند و نام سرور و شماره پورت را برای اتصال مشخص می‌کند.

  • سازنده کلاس Socket سعی می‌کند مشتری را به سرور و شماره پورت مشخص شده متصل کند. اگر ارتباط برقرار شود، مشتری دارای یک شی Socket قابل ارتباط با سرور می‌شود.

  • در سمت سرور، متد accept() یک ارجاع به یک سوکت جدید روی سرور را که به سوکت مشتری متصل است، برمی‌گرداند.

پس از برقراری اتصال‌ها، ارتباط با استفاده از جریان‌های ورودی/خروجی (I/O streams) امکان‌پذیر است. هر سوکت دارای یک OutputStream و یک InputStream است. OutputStream مشتری به InputStream سرور متصل است و InputStream مشتری به OutputStream سرور متصل است.

TCP یک پروتکل ارتباط دوطرفه است، بنابراین داده‌ها می‌توانند همزمان از طریق هر دو جریان ارسال شوند. کلاس‌های مفیدی که مجموعه کاملی از متدها را برای پیاده‌سازی سوکت‌ها فراهم می‌کنند، در ادامه آمده است.

متدهای کلاس ServerSocket

کلاس java.net.ServerSocket برنامه‌های سرور برای به دست آوردن یک پورت و گوش دادن به درخواست‌های مشتری استفاده می‌شود.

کلاس ServerSocket دارای چهار سازنده است −

شماره متد و توضیحات
1

public ServerSocket(int port) throws IOException

تلاش برای ایجاد یک سوکت سرور متصل به پورت مشخص شده. در صورتی که پورت توسط برنامه دیگری متصل شده باشد، یک استثناء رخ می‌دهد.

2

public ServerSocket(int port, int backlog) throws IOException

مشابه سازنده قبلی است، پارامتر backlog تعداد مشتریان ورودی را که در صف انتظار ذخیره می‌شوند، مشخص می‌کند.

3

public ServerSocket(int port, int backlog, InetAddress address) throws IOException

مشابه سازنده قبلی است، پارامتر InetAddress آدرس IP محلی را برای اتصال مشخص می‌کند. از InetAddress برای سرورهایی استفاده می‌شود که ممکن است چندین آدرس IP داشته باشند و سرور بتواند مشخص کند که کدام یک از آدرس‌های IP خود را برای درخواست‌های مشتری بپذیرد.

4

public ServerSocket() throws IOException

ایجاد یک سوکت سرور بدون اتصال. در صورت استفاده از این سازنده، هنگامی که آماده اتصال سوکت سرور هستید، از متد bind() استفاده کنید.

اگر سازنده ServerSocket استثناءی ایجاد نکند، به این معناست که برنامه شما با موفقیت به پورت مشخص شده متصل شده است و برای درخواست‌های مشتری آماده است.

متدهای متداول کلاس ServerSocket به شرح زیر است −

شماره متد و توضیحات
1

public int getLocalPort()

پورتی را که سوکت سرور روی آن گوش می‌دهد، بازمی‌گرداند. این متد مفید است اگر شما در سازنده عدد 0 را به عنوان شماره پورت پاس داده‌اید و به سرور اجازه داده‌اید یک پورت برای شما پیدا کند.

2

public Socket accept() throws IOException

منتظر یک مشتری ورودی می‌ماند. این متد تا زمانی که یا یک مشتری به سرور در پورت مشخص شده متصل شود و یا سوکت تایم‌اوت شود (اگر مقدار تایم‌اوت با استفاده از متد setSoTimeout() تنظیم شده باشد)، بلوکه می‌شود. در غیر این صورت، این متد به طور نامحدود بلوکه می‌شود.

3

public void setSoTimeout(int timeout)

مقدار تایم‌اوت را برای مدت زمانی که سوکت سرور در هنگام accept() منتظر یک مشتری می‌ماند، تنظیم می‌کند.

4

public void bind(SocketAddress host, int backlog)

سوکت را به سرور و پورت مشخص شده در شیء SocketAddress متصل می‌کند. از این متد استفاده کنید اگر شما از سازنده بدون آرگومان برای ServerSocket استفاده کرده باشید.

زمانی که ServerSocket متد accept() را فراخوانی می‌کند، این متد تا زمانی که یک مشتری متصل شود برنمی‌گردد. پس از اتصال یک مشتری، ServerSocket یک Socket جدید را روی یک پورت نامشخص ایجاد می‌کند و ارجاعی به این Socket جدید برمی‌گرداند. حالا ارتباط TCP بین مشتری و سرور برقرار است و ارتباط می‌تواند شروع شود.

متدهای کلاس Socket

کلاس java.net.Socket سوکتی را نمایش می‌دهد که هم مشتری و هم سرور برای ارتباط با یکدیگر استفاده می‌کنند. مشتری یک شیء Socket را با ایجاد یک شیء سازنده دریافت می‌کند، در حالی که سرور یک شیء Socket را از مقدار بازگشتی متد accept() دریافت می‌کند.

کلاس Socket دارای پنج سازنده است که مشتری برای اتصال به سرور استفاده می‌کند −

شماره متد و توضیحات
1

public Socket(String host, int port) throws UnknownHostException, IOException.

این متد سعی می‌کند به سرور مشخص شده در پورت مشخص شده متصل شود. اگر این سازنده هیچ استثناء‌ای را پرتاب نکند، اتصال موفق بوده و مشتری به سرور متصل شده است.

2

public Socket(InetAddress host, int port) throws IOException

این متد همانند سازنده قبلی است، به جز اینکه میزبان با یک شیء InetAddress مشخص می‌شود.

3

public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.

به میزبان و پورت مشخص شده متصل می‌شود و یک سوکت در میزبان محلی در آدرس و پورت مشخص شده ایجاد می‌کند.

4

public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.

این متد همانند سازنده قبلی است، به جز اینکه میزبان با یک شیء InetAddress به جای یک رشته مشخص می‌شود.

5

public Socket()

یک سوکت بدون اتصال ایجاد می‌کند. از متد connect() برای اتصال این سوکت به یک سرور استفاده کنید.

زمانی که سازنده Socket برگردانده می‌شود، به سادگی یک شیء Socket را نیافته‌ایم، بلکه در واقع سعی در اتصال به سرور و پورت مشخص شده را داشته‌ایم.

برخی از متدهای مورد علاقه در کلاس Socket در ادامه آمده است. توجه کنید که هم مشتری و هم سرور یک شیء Socket دارند، بنابراین این متدها می‌توانند توسط هر دو مشتری و سرور فراخوانی شوند.

شماره متد و توضیحات
1

public void connect(SocketAddress host, int timeout) throws IOException

این متد سوکت را به میزبان مشخص متصل می‌کند. این متد تنها زمانی لازم است که شما از سازنده بدون آرگومان ساکت استفاده می‌کنید.

2

public InetAddress getInetAddress()

این متد آدرس کامپیوتر دیگری که این سوکت به آن متصل است را برمی‌گرداند.

3

public int getPort()

پورتی که سوکت به آن در ماشین از راه دور بسته شده است را برمی‌گرداند.

4

public int getLocalPort()

پورتی که سوکت به آن در ماشین محلی بسته شده است را برمی‌گرداند.

5

public SocketAddress getRemoteSocketAddress()

آدرس سوکت از راه دور را برمی‌گرداند.

6

public InputStream getInputStream() throws IOException

جریان ورودی سوکت را برمی‌گرداند. جریان ورودی به جریان خروجی سوکت از راه دور متصل است.

7

public OutputStream getOutputStream() throws IOException

جریان خروجی سوکت را برمی‌گرداند. جریان خروجی به جریان ورودی سوکت از راه دور متصل است.

8

public void close() throws IOException

سوکت را بسته و این شیء Socket دیگر قابلیت اتصال به هیچ سرور دیگری را ندارد.

متدهای کلاس InetAddress

این کلاس یک آدرس پروتکل اینترنت (IP) را نشان می‌دهد. در ادامه متدهای مفیدی که در زمان برنامه‌نویسی سوکت به آنها نیاز دارید آورده شده است:

شماره متد و توضیحات
1

static InetAddress getByAddress(byte[] addr)

با استفاده از آدرس IP خام، یک شیء InetAddress برمی‌گرداند.

2

static InetAddress getByAddress(String host, byte[] addr)

یک InetAddress بر اساس نام میزبان و آدرس IP ارائه شده ایجاد می‌کند.

3

static InetAddress getByName(String host)

با استفاده از نام میزبان، آدرس IP میزبان را تعیین می‌کند.

4

String getHostAddress()

رشته آدرس IP را به صورت متنی برمی‌گرداند.

5

String getHostName()

نام میزبان برای این آدرس IP را برمی‌گرداند.

6

static InetAddress InetAddress getLocalHost()

میزبان محلی را برمی‌گرداند.

7

String toString()

این آدرس IP را به یک رشته تبدیل می‌کند.

مثال سوکت مشتری

کد زیر یک برنامه مشتری GreetingClient است که با استفاده از یک سوکت به یک سرور متصل شده و سلامی را ارسال می‌کند و سپس منتظر یک پاسخ است:

مثال


// File Name GreetingClient.java
import java.net.*;
import java.io.*;

public class GreetingClient {

   public static void main(String [] args) {
      String serverName = args[0];
      int port = Integer.parseInt(args[1]);
      try {
         System.out.println("Connecting to " + serverName + " on port " + port);
         Socket client = new Socket(serverName, port);
         
         System.out.println("Just connected to " + client.getRemoteSocketAddress());
         OutputStream outToServer = client.getOutputStream();
         DataOutputStream out = new DataOutputStream(outToServer);
         
         out.writeUTF("Hello from " + client.getLocalSocketAddress());
         InputStream inFromServer = client.getInputStream();
         DataInputStream in = new DataInputStream(inFromServer);
         
         System.out.println("Server says " + in.readUTF());
         client.close();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

مثال سرور سوکت

برنامه GreetingServer زیر نمونه‌ای از یک برنامه سرور است که از کلاس Socket برای گوش دادن به مشتریان در یک شماره پورت مشخص شده توسط آرگومان خط فرمان استفاده می‌کند:

مثال


// File Name GreetingServer.java
import java.net.*;
import java.io.*;

public class GreetingServer extends Thread {
   private ServerSocket serverSocket;
   
   public GreetingServer(int port) throws IOException {
      serverSocket = new ServerSocket(port);
      serverSocket.setSoTimeout(10000);
   }

   public void run() {
      while(true) {
         try {
            System.out.println("Waiting for client on port " + 
               serverSocket.getLocalPort() + "...");
            Socket server = serverSocket.accept();
            
            System.out.println("Just connected to " + server.getRemoteSocketAddress());
            DataInputStream in = new DataInputStream(server.getInputStream());
            
            System.out.println(in.readUTF());
            DataOutputStream out = new DataOutputStream(server.getOutputStream());
            out.writeUTF("Thank you for connecting to " + server.getLocalSocketAddress()
               + "\nGoodbye!");
            server.close();
            
         } catch (SocketTimeoutException s) {
            System.out.println("Socket timed out!");
            break;
         } catch (IOException e) {
            e.printStackTrace();
            break;
         }
      }
   }
   
   public static void main(String [] args) {
      int port = Integer.parseInt(args[0]);
      try {
         Thread t = new GreetingServer(port);
         t.start();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }
}

کلاینت و سرور را کامپایل کنید و سپس سرور را به شکل زیر راه‌اندازی کنید:


$ java GreetingServer 6066
Waiting for client on port 6066...

برنامه کلاینت را به شکل زیر بررسی کنید:

خروجی


$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!