راسخون

..:: آموزش جامع سوکت نویسی با زبان جاوا ::..

siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 





siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 

siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 

siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
توضیحات مرحله اول : ایجاد یک سرور سوکت (ServerSocket)
 
 
ServerSocket چیست :
 
سرور سوکت یکی از کلاسهایی می باشد
که در پکیج java.net برا پیاده سازی سرور شبکه
طراحی شده است ، که شما به راحتی می توانید
بدونه نوشتن برنامه سرورتون رو پباده سازی کنید.
 
 
فراخوانی سازنده سرور سوکت بفرم زیر می باشد:
 
کد PHP:
ServerSocket server = new ServerSocket(PortName, queueLength);  
 
در این عبارت PortName یعنی پورتی که باید به حالت لیستن یا آماده باش دربیاد
تا کلاینتها بتوانند به آن متصل شوند
و queueLength یعنی تعداد کلاینتی که می توانند به وسیله پورت موردنظر
به سرور وصل شوند.
 
 
 
پس حالا این یعنی 
 
کد PHP:
ServerSocket server = new ServerSocket(80, 100);  
صدتا کلاینت می توانند به پورت 80 سرور وصل شوند.
 
 
 
اطلاعات عمومی :
 
این قسمت
کد PHP:
= new ServerSocket(PortName, queueLength);  
یعنی ما سازنده کلاس سرورسوکت (که در پکیج java.net قرار دارد) رو صدا
میزنیم و یک مقدار که بعنوان ارگومان براش در نظر گرفته ایم که همون پورت نیم
و تعداد کلاینت بود رو براش ارسال می کنیم.
 
در اصل کار سازند مثل فرمان Form /Load در زبان ویژوال بیسیک هستش یعنی
بدونه صدا زدن اجرا میشه مثل تابع نیست که حتما در برنامه اول صداش
بزنیم بعد اون اجرا بشه .(خودکار اجرا میشه)
این رو گفتم که بدونید کار سازند در برنامه چیه  
 
حالا شماره پورت توسط سرویس گیرنده ها برای یافتن برنامه سرویس دهنده
بر روی کامپیوتر سرویس دهنده بکار گرفته می شود.
غالبا به این عمل Handshake Point یا (نقطه دست دهی)گفته می شود.
 
اگر صف برای تقاضا پر باشد سرویس دهنده اتصالات سرویس گیرنده را رد می کند.
 
سازنده که در بالا براتون توضیح دادم مبادرت به ایجاد پورتی می کند
که سرویس دهنده منتظر برقراری اتصال از سوی سرویس گیرنده هاست.
این فرایند بعنوان مقید کردن سرویس دهنده به پورت (Binding The Server To The Port) 
نامیده می شود.
هر سرویس گیرنده تقاضای برقراری اتصال به سرویس دهنده از طریق 
این پورت رو خواهد کرد.این رو هم بدانید در هر زمان فقط یک برنامه می تواند
از طریق پورت مشخص شده با سرویس دهنده ارتباط برقرار نماید.
 
 
 
 
نکته:
 
شماره های پورت می تواند مابین 0 تا 65535 باشند.
اکثر سیستم های عامل شماره های پورت زیر 1027 رابرای سرویسهای سیستم
رزرو کرده اند(همانند ایمیل و...)عموما از این پورتها نباید
بعنوان پورتهای اتصالی در برنامه
استفاده شود.
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
زنگ تفریـــــــــــح  
 
 
 
گفتم شاید از خوندن مطالب بالا یکم خسته شدین یه 
تفریح کوچیک بهتون بدم دوباره از نوع شروع کنم
 
 
 
خوب تفریح ما نوشتن یه برنامه برا لیستن کردن پورتهای سیستممون می باشد
 
 
الان شاید پیش خودتون فرض کنید که یه هزار خطی میشه 
 
نه جانم
 
اگر به مفاهیم بالا که توضیح دادم خوب توجه کرده باشید
برا لیستن کردن ما فقط از یک خط برنامه در
زبان شیرین جاوا می تونیم این کار رو انجام بدهیم 
 
 
فقط یک خط که اونم اینه
کد PHP:
ServerSocket server = new ServerSocket(21);  
این یک خط باعث میشه که پورت 21 ما به حالت لیستن در بیاد.........
 
حالا اگر این قطعه کد رو در یک کلاس جای دهید
به راحتی پورت مورد نظر رو برا شما به حالت 
لیستن در می آورد این کار برا ویروس نویسان عالیه
یعنی با همین یه قطعه کد می توانند 
یه ویروس برا لیستن کردن پورت موردنظرشون
آماده کنند 
 
 
اینم از زنگ تفریح
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
توضیحات مرحله دوم : انتظار برای اتصال (فال گوش ماندن)
 
 
خوب برنامه هایی که تحت شبکه کار می کنند هر اتصال سرویس گیرنده
را با یک شی سوکت مدیریت می کنند.
 
دومین مرحله، در فرآیند ایجاد اتصال گوش دادن به تقاضاهای اتصال
از سوی سرویس گیرنده است........
برای گوش دادن به اتصال یک سرویس گیرنده برنامه ما باید یک متد accept()
از ServerSocket را به صورت زیر فراخوانی کند
 
 
کد PHP:
Socket socket=server.accept()  
 
توضیحات کد بالا
 
 
ما در این کد یک سوکت ایجاد می کنیم با نام socket ویک
مقدار رو به این شی از کلاس تعلق میدهیم مقداری که به این شی میدهیم
در بردارنده عملیات موفقیت آمیز در اتصال سرویس گیرنده به پورت در حال لیستن
سرویس دهنده می باشد که اگر سرویس گیرنده با موفقیت به سرور ما متصل شد
یه سوکت برا انجام کارهای ارسال و دریافت ایجاد می شود.
 
 
این سوکتی که ایجاد می شود در اصل به سرویس دهنده امکان تعامل با سرویس گیرنده را میدهد.
در واقع تعاملات صورت گرفته با سرویس گیرنده بر روی پورتهای متفاوت سرویس دهنده
از نقطه دست دهی صورت میگیرد.
این حالت به پورت مشخص شده در مرحله اول امکان میدهد تا مجددا
در یک سرویس دهنده چندنخی برای پذیرش اتصال یک سرویس گیرنده دیگر
بکار گرفته شود.
 
 
 
در اصل تمام کارهایی که در این مرحله انجام میشود
ایجاد یک سوکت در عملیات موفقیت آمیز کانکشن سرویس گیرنده به سرویس دهنده 
می باشد.
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
توضیحات مرحله سوم : بدست آوردن استریم I/O سوکت
 
 
 
اگر متن بالا رو بدقت خوانده باشید میدانید که زمانی کامپیوتر
سرویس گیرنده ما به پورت لیستن سرور با موفقیت وصل شد یک سوکت
ایجاد میشود......
 
 
خوب حالا سوکت ایجاد شده باید توانایی ارسال و دریافت یا خواندن
و نوشتن اطلاعات را داشته باشد.
 
 
برا این کار سراغ سومین مرحله اومدیم 
 
 
کار این مرحله بدست آوردن شی های OutputStream و InputStream می باشد.
این شی ها به سرویس دهنده امکان برقراری ارتباط با سرویس گیرنده را از طریق 
ارسال و دریافت بایت ها را فراهم می کنند.
 
حالا این دو شی که بر روی سوکت ما فراخوانی می شوند قابلیتهای خواندن و نوشتن
رو نیز به سوکت می دهند.
 
خوب الان سرویس دهنده مبادرت به ارسال اطلاعات به سرویس گیرنده از طریق
یک OutputStream کرده و اطلاعات را از سرویس گیرنده از طریق یک
InputStream دریافت می کند.
در حقیقت این دوشی بر روی سوکت ایجاد شده فراخوانی شده اند
درکل ما داریم از سوکت استفاده می کنیم .....
 
حالا سرویس دهنده متد getOutputStream را بر روی سوکت فراخوانی می کند
تا یک مراجعه به OutputStream سوکت بدست اورد.همچنین متد getInputStream را
بر روی سوکت فراخوانی می کند تا یک مراجعه به InputStream تهیه شود.
 
 
 
 
شی های استریم می توانند برای ارسال یا دریافت بایتهای مجزا یا دنباله ای از بایتها
از طریق متد write از OutputStream و متدread از InputStream بکار گرفته شوند.
 
 
 
خوب حالا برا دوستان سوال پیش میاد که سوکت رو با چه سورسی
ترکیب کنیم که توانایی خواندن و نوشتن رو پیدا کند
 
 
به این شکل به سوکتمون قابلیت خواندن میدهیم
 
کد PHP:
ObjectInputStream in=new ObjectInputStream(socket.getInputStream());  
به این شکل به سوکتمون قابلیت نوشتن میدهیم
 
کد PHP:
  ObjectOutputStream out=new ObjectOutputStream(socket.getOutputStream());  
 
 
 
 
حالا خوشبختانه سوکت ما قادر به ارسال یا نوشتن و دریافت یا خواندن می باشد.
 
 
 
 
 
 
 
بازم این رو بگم اگه سوالی در این باب براتون پیش اومد با پی ام اطلاع دهید. 
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
توضیحات مرحله چهارم: پردازش
 
 
 
خوب این قسمت هم از نامش دیگه معلومه ولی یکم در موردش بگم بد نیست
 
 
 
 
در این مرحله سرویس دهنده و سرویس گیرنده از طریق شی های 
OutputStream و InputStream با یکدیگر ارتباط برقرار میکنند
 
اینجاست که دیگه اطلاعات رد و بدل میشن....
 
این رو هم بدونید انتقال داده بر روی شبکه یکپارچه بوده و کاملا
توسط جاوا رسیدگی میشود.
 
 
 
============================================
 
 
توضیحات مرحله پنجم : بستن اتصال
 
 
این مرحله هم اخرین مرحله می باشد که کار آن خاتمه دادن به اتصال است.
پس از اینکه سرویس دهنده و سرویس گیرنده به ارتباط خود خاتمه دادند،
سرویس دهنده با استفاده از متد close به اتصال خاتمه میدهد(Disconnetct)
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
سورس سر فایل برنامه همراه سازند
 
 
سازند در اصل همانطور که براتون گفتم مثل Form/Load ویژوال بیسیک می مونه
بیشتر برا کارهایی مثل ران شدن فرمانهای دلخواه در زمان اجرای برنامه
یا مقدار دادن به متغییرهاازش
استفاده می کنیم که در اینجا سورس کارهای
گرافیکی رو در سازند قرار داده ایم 
 
کد PHP:
 
 
 
import java.io.EOFException; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 
 
 
    public class Server1 extends JFrame{ 
 
        private JTextField enterField; 
            private JTextArea displayArea; 
                private ObjectOutputStream output; 
                    private ObjectInputStream input; 
        private ServerSocket server; 
            private Socket connection; 
                private int counter=1; 
                 
                public Server1() 
                { 
                    super("Server"); 
                     
                    enterField=new JTextField(); 
                        enterField.setEditable(false); 
                            enterField.addActionListener(new ActionListener(){ 
                             
                                public void actionPerformed(ActionEvent event) 
                                { 
                                sendData(event.getActionCommand()); 
                                    enterField.setText(""); 
                                } 
                            }); 
                             
                add(enterField,BorderLayout.NORTH); 
                displayArea=new JTextArea(); 
                    add(new JScrollPane(displayArea)); 
                     
                        setSize(300,150); 
                            setVisible(true);  
}
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
فکر کنم در مورد سورس بالا یکم توضیح
بدم بهتر باشه تا اینکه همینجوری برویم سراغ متدهایه دیگه ای از برنامه
 
 
 
قسمت 1 
کد PHP:
import java.io.EOFException; 
import java.io.IOException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*;  
خوب سورس بالا تعریف سرفایلهای برنامه می باشدک که
ما با این کار می توانیم از توابع وکلاسهای موردنظر
در برناممون استفاده کنیم.(در کامنتهای قبلی که دادم این قسمت رو بصورت کامل توضیح دادم)
 
 
 
 
قسمت 2 
 
کد PHP:
public class Server1 extends JFrame{}  
این قسمت شروع کلاس ما می باشد
اگر دقت کرده باشید کلاس ما توسعه یافته ای از کلاس JFrame هستش
در اصل ما با استفاده از extends این کار رو انجام میدهیم
در کل این کار باعث می شود که کلاس ما بصورت گرافیکی
پیاده سازی شود.
دستورات رو هم در میان {} قرار میدهیم.
 
 
قسمت 3 
کد PHP:
        private JTextField enterField; 
            private JTextArea displayArea; 
                private ObjectOutputStream output; 
                    private ObjectInputStream input; 
        private ServerSocket server; 
            private Socket connection; 
                private int counter=1;  
در این قسمت ما متغیرهایمان رو بصورت پیش فرض پابلیک و بصورت
نمونه تعرف کرده ایم. در اصل متغیرهایی که بعد از تعرف نام کلاس قرار میگیرند
بصورت ضمنی پابلیک تعریف می شوند.
این private هم که به متغیرمون اضافه کردم 
دلیل بر این هستش که می خواهم بصورت نمونه باشند.
 
 
قسمت 4 
کد PHP:
     public Server1() 
                { 
                    super("Server"); 
                     
                    enterField=new JTextField(); 
                        enterField.setEditable(false); 
                            enterField.addActionListener(new ActionListener(){ 
                             
                                public void actionPerformed(ActionEvent event) 
                                { 
                                sendData(event.getActionCommand()); 
                                    enterField.setText(""); 
                                } 
                            }); 
                             
                add(enterField,BorderLayout.NORTH); 
                displayArea=new JTextArea(); 
                    add(new JScrollPane(displayArea)); 
                     
                        setSize(300,150); 
                            setVisible(true);  
}
 
این قسمت هم سازند برنامه هستش. در اصل نام سازند
همیشه هم نام با نام کلاس و بصورت پابلیک می باشد.
در کل عملکرد سازند دقیقا شبیه تابع می باشد ولی با اندکی تفاوت .....
 
تفاوتش با متد اینه که هیچ مقدار برگشتی ندارد حتی Void
دیگه همه چیزش مثل متد هایه دیگه برنامه است(اینم همون اندک تفاوتی که گفتم  )
 
 
خوب یه سری کد هم تو سازند استفاده کردم برا هوشمند کردن
تکست فیلدمون در اصل اومدم از واسط ActionListener برا فال گوش ماندن
تکست فیلد استفاده کردم این واسط دارای یک تابع به نام ActionEvent می باشد
که کارش از اسمش معلومه  رویدادهای اتفاق افتاده رو که واسط ActionListener ضبط کرده
رو کامپایل می کند.
 
 
 
قسمت 5 
 
کد PHP:
  sendData(event.getActionCommand());  
این قسمت موظفه که هرچی در تکست فیلد وارد کردیم رو به صورت
رشته به تابع sendData ارسال کند.
 
 
قسمتهایه دیگه هم کار تنظیمات کامپونتهایه روی فرم رو انجام میدهند.
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
متد دوم از کلاس Server1
 
کد PHP:
      public void runServer() throws Exception
                {
                
                try
                {
                    server=new ServerSocket(12345,100);
                    
                    while(true)
                    {
                        try
                    {
                    waitForConnection();
                        getStreams();
                        processConnection();
                    }
                    catch(EOFException eof)
                    {
                        displayMessage("\nServer terminated connection");
                    }
                    finally
                    {
                    closeConnection();
                    ++counter;
                    }
                }
                    }
                catch(IOException io)
                {
                io.printStackTrace();
                }
                }  
خوب اسم این متد رو runServer گذاشتم
تا درتابع اصلی با صدا زدن این تابع موتور برناممون رو روشن کنم 
منظورم از این حرف اینه که داخل این متد یه سری کد استفاده کردم
که مبنی بر فراخوانی تمام تابع های برناممون هستش
با فراخوانی همین یک تابع در برنامه اصلی تمام تابع های موجود در کلاس سرور
فراخوانی و اجرا می شوند.......
 
 
 
زمانی که با تابع اصلی تابع runServer رو فراخوانی می کنیم این 
قطعه کد که سازند کلاس ServerSocket رو فراخوانی می کند
کد PHP:
server=new ServerSocket(12345,100);  
سریع به اجرا در میاد تا پورت 12345 در سرور ما در حالت لیستن قرار گیرد
 
 
از try .... catch....finally هم در ادامه سورسمون استفاده کرده ایم
 
کا این سه گزینه کنترل کردن استثناء های رخ داده در برنامه می باشد
در اصل ما با این سه گزینه برناممون رو بلوکه کردیم که
اگر خطایی رخ داد سریع به قسمت دیگه ای از
برنامه منتقلش کن که کار برنامه متوقف نشه.
 
نکته
از گزینه finally علاوه بر عملیات بالا کار آزاد سازی حافظه
اخذ شده از سیتم را نیز انجام میدهد. 
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
متد سوم از کلاس Server1
کد PHP:
 
 public void waitForConnection()throws Exception
                {
                    displayMessage("Waite For Connection...\n");
                        connection=server.accept();
                            displayMessage("Connection "+counter+"received from: "+connection.getInetAddress().getHostName());
                }
}  
 
 
با این متد ما منتظر کانکشن از سوی کلاینت می مانیم
زمانی که اتصال با موفقیت انجام شد سورس کد زیر ران میشه
کد PHP:
connection=server.accept();  
زمانی که این قطعه کد ران شد یک سوکت با موفقیت ایجاد میشه.......
این همان چیزیه که مابرا ارسال و دریافت اطلاعات ازش استفاده می کنیم 
 
 
 
کد PHP:
connection.getInetAddress().getHostName()  
قطعه کد بالا هم برا بدست اوردن نام کامپیوتری که
به سرور ما کانکشن شده استفاده میشود
siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
متد پنجم از کلاس Server1
 
 
کد PHP:
  private void processConnection()throws IOException
                    {
                        String message="Connection Successfully";
                            sendData(message);
                            
                            setTextFieldEditable(true);
                            
                            do{
                            
                                try{
                                    message=(String)input.readObject();
                                        displayMessage("\n"+message);}
                                catch(ClassNotFoundException e)
                                {
                                    displayMessage("\n Unknown object type recived");
                                }
                                
                            
                            
                            }while(message.equals("Client >> TERMINATE"));
    
                    }  
این متد هم در برنامه زمانی که ما از طرف مقابل یا همون 
سرویس گیرنده بوسیله ی سوکت اطلاعات دریافت می کنیم فراخوانی میشود
کار این تابع خواندن اطلاعاتی هستش که سوکت از طرف کلاینت بوسیله پروتکل TCP
برای ما اورده است.
 
 
 
کد PHP:
message=(String)input.readObject();  
قطعه کد بالا عمل typecasting رو برا ما انجام میدهد.
در اصل اطلاعات سوکت که بصورت شی هست توسط کد بالا به String
تبدیل می شود.

 

siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
متد ششم از کلاس Server1
 
کد PHP:
   private void closeConnection()
                    {
                    displayMessage("\nTerminating connection\n");
                        setTextFieldEditable(false);
                        
                            try
                            {
                                output.close();
                                    input.close();
                                        connection.close();
                            }
                            catch(IOException exe)
                            {
                            exe.printStackTrace();
                            }
                            }  
کار این متد هم دیگه از نامش معلومه
پایان دادن با اتصالات.(close)
 
زمانی که انتقال اطلاعات کامل شد متد processConnection باز میگردد
وبرنامه متد closeConnection رو برای بستن استریم های مرتبط
با سوکت فراخوانی کرده وسوکت بسته می شود.
سپس سرویس دهنده منتظر اتصال بعدی از سوی سرویس گیرنده 
می ماند.

 

siryahya کاربر طلایی1
|
تعداد پست ها : 158652
|
تاریخ عضویت : اسفند 1389 
متد هفتم از کلاس Server1
 
کد PHP:
   private void sendData(String messg) 
                    { 
                     
                        try{ 
                            output.writeObject("Server >> "+messg); 
                                output.flush(); 
                                    displayMessage("\nServer >> "+messg); 
                        } 
                        catch(IOException exe) 
                        { 
                        displayArea.append("\nError writeing object"); 
                        } 
                        }  
 
 
این متد هم عملیات ارسال رو برا ما انجام میدهد.
زمانی که کاربر برنامه ی سرویس دهنده ، رشته ای در تکست فیلد
وارد می کند و کلید Enter را فشار میدهد متد actionPerformed رشته
وارد شده رو خوانده و ان را از طریق متد sendData که همین متد می باشد 
ارسال می کند.
 
 
این رو هم بدانید که در اینجا سرویس دهنده اتصال را دریافت ، آنرا پردازش،
بسته و در انتظار اتصال بعدی باقی می ماند.