جميل جداً :D
لا اله الا الله .. محمد رسول الله
(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)
يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين
جميل جداً :D
لا اله الا الله .. محمد رسول الله
(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)
يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين
بنت اليمن كتب:بيطلع كود html يعني كاني عم بطلب الكود من المتصفح يا ترا فيني اخذ كود PHP يعني مو بس كود ال html حتى ال PHP اذا كانت صفحات ديناميكيةحياك shadooo ... و من التجربة نعم بيطلع معك كود php و محتويات اي ملف مهما كان نوعه ...
عفوا ولكن لم يخرج سوا كود ال html
بالنسبة لما كتبت
حياك الله اخي shadooo
عندما جربت مسبقاً ظهر لي انه يتم نوع من التضمين للـ php داخل وسوم الـ html
من التجربة طلع معي التالي :
امممممممم ممكن تعطيني فرصة اشوف المسألة ... لان العملية في النهاية هي قراءة ملف نصي
دعنا نفكر في قراءة الملف كما هو بأكواده كملف php ...
لا اله الا الله .. محمد رسول الله
(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)
يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين
متابع :)
السلام عليكم ورحمه الله وبركاته ،
عندما تعاملنا المره السابقه مع URL ، وقمنا بطباعه محتوياته على شاشه Console أو حتى لو كانت JTextArea ، كان الناتج هو Raw Content of page ، أي كانت محتويات صفحه html هي كود html الخاص بها (html tags) ، وفي حال كانت صوره فإن المحتويات تكون هنا Binary Data وهي محتويات الصوره ، وفي حال التلاعب بأحد هذه البتات الموجوده في الصوره ، فإن ذلك يؤثر على الصوره بالطبع .
المهم ، ماذا يحصل في حال أردنا طباعه المحتويات كما هي ، أي نطلب الصفحه ، ونطبع محتوياتها كما هي . وهنا جافا وفرت لنا :
javax.swing.text.html javax.swing.text.html.parser javax.swing.JEditorPane
الكلاس الأول والثاني يستخدمان لعمل parse لمحتويات الصفحه مثلا أردنا أن نعرف معلومه ما في كود html أو نعرض الـ tags بشكل معين ، أما الثالث والذي سنستخدمه يستخدم الكلاسين السابقين ويريحنا من الكثير من العناء ، وكل ما علينا أن نعطي هذا الكلاس الـ URL ، وسوف يعرض لنا الشاشه في JEditorPane .
هنا في موضوعنا اليوم ، سوف نتناول كيفيه التعامل مع JEditorPane والتعامل مع الأحداث التي يولدها HyperlinkEvent .
JEditorPane
==========
كما ذكرنا قبل قليل ، كل ما علينا عمل Object من هذا الكلاس ، وبعدها سوف يقوم هو بالباقي ويعرض لك المحتويات . وهذه دوال البناء التي نستطيع من خلالها عمل كائن :
public JEditorPane( ) public JEditorPane(URL initialPage) throws IOException public JEditorPane(String url) throws IOException public JEditorPane(String mimeType, String text)
الداله الأولى ، لا تستقبل أي معامل ، فقط تنشئ كائن ، لكن نستطيع أعطائها قيمه ما فيما بعد باستخدام أحد دوال الـ set :
public void setPage(URL page) throws IOException public void setPage(String url) throws IOException public void setText(String html
لاحظ ال IOExceptions الذي تنتجه هذه الداول ، وهو يمكن أن يولد MalformedURLException في لم يستطع التعرف على البرتوكول في URL .
أيضا عندما نتعامل مع JEditPane ونريد عرض محتوياته ، يجب علينا في حال أردنا أن نتعامل مع الـ Hyperlink (الوصلات) الموجوده في هذه المحتويات :
1- أن نقوم بوضع خاصيه عدم التعديل في JEditorPane :
jep.setEditable(false);
(شاهد المثال القادم) .
2- أن نتعامل مع الـ Event الذي يولد نتيجه الضغط على الـ Hyperlink أو المرور فيه ، أو الخروج منه .
مثال لداله البناء الأولى ، لاحظ هنا أن jep.setEditable(false); على شكل تعليق ، قم بتنفيذ البرنامج ، وسوف تلاحظ أنك تستطيع الكتابه في المحتويات ، لكن تستطيع التعامل مع الـ Hyperlink ، جرب الوقوف في أحدها وسيظهر مثله مثل أي text أخر .
import javax.swing.JFrame;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import java.io.IOException;
public class Demo
{
public static void main (String args[])
{
JEditorPane jep = new JEditorPane();
//jep.setEditable(false);
try
{
jep.setPage("http://localHost");
}
catch ( IOException e)
{
jep.setContentType("text/html");
jep.setText("<html>Could Not Load http://localHost</html>");
}
JFrame app = new JFrame("Display http://localHost");
app.add( new JScrollPane(jep) );
app.setSize(500,300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
}بعد تنفيذك للبرنامج ، قم بفك التعليق وتشغيل البرنامج مره أخرى، وهنا سوف تلاحظ أن شكل الماوس تغير عندما تتوقف عند أي Hyperlink ، ولكن في حال ضغط عليه لن يعمل أيضا ، والسبب لأننا لم نوضع Listener يتعامل مع هذا الـ event .
دوال البناء الباقيه :
public JEditorPane(URL initialPage) throws IOException public JEditorPane(String url) throws IOException public JEditorPane(String mimeType, String text)
الأولى والثانيه ، يستقبلان URL سواء كString أو URL Object ، وهنا مباشره سوف يتصل بـ URL ويعرض لك المحتويات في JEdtorPan ، نفس المثال السابق باستخدام الداله الأولى :
import javax.swing.JFrame;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import java.io.IOException;
public class Demo
{
public static void main (String args[])
{
JEditorPane jep = null;
try
{
jep = new JEditorPane("http://localHost");
jep.setEditable(false);
}
catch ( IOException e)
{
jep.setContentType("text/html");
jep.setText("<html>Could Not Load http://localHost</html>");
}
JFrame app = new JFrame("Display http://localHost");
app.add( new JScrollPane(jep) );
app.setSize(500,300);
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
}أما
داله البناء :
public JEditorPane(String mimeType, String text)
فهي لا تتصل بURL كما في دوال البناء الأخرى (لذلك لا تولد Exception ) ، فقط تأخذ البيانات من المعامل الثاني text (أرسلها في وقت التشغيل runtime ) ، والمعامل الأول يحدد نوع البيانات التي يتعامل معها .
مثل :
JEditorPane jep = new JEditorPane("text/html", "<html><h1>Hello World!</h1> <h2>Goodbye World!</h2></html>");ويمكن أن نستخدم هذه الداله ، لطباعه محتويات تقرير ، أو Help File ، حيث هي فقط تستقبل البيانات ، وتطبعها مباشره .
مثال ، لطباعه سلسله فيبوناسي Fibonacci على شكل قائمه مرتبه order List :
/
/ print Fibonacci number from 0-50
// using html tage : <ol> <li>first item <li> second item </ol>
import javax.swing.JFrame;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
public class Demo
{
public static void main (String args[])
{
StringBuffer str = new StringBuffer("<html><body><h1>Fibonacci Series</h1><ol>");
int first = 0;
int second = 1;
for (int i=0; i<50; i++)
{
str.append("<li>");
str.append("<font color=red>" + first + "</font>");
int tmp = first + second;
first = second;
second = tmp;
}
str.append("</ol></body></html>");
JEditorPane jep = new JEditorPane("text/html",str.toString());
jep.setEditable(false);
JFrame app = new JFrame("Fibonacci Sereis");
app.add ( new JScrollPane(jep) );
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setSize(500,300);
app.setVisible(true);
}
}
التعامل مع الـ Hyperlink :
================
كما ذكرنا قبل قليل ، للتعامل مع الـ Hyperlink في الصفحه ، يجب أن :
1- نغلق خاصيه التعديل على الصفحه
2- نسجل listener على الevent الخاص بالـ hyperlink ( وهو يتولد اما بالضغط على اللنك ، أو المرور فيه ، أو الخروج منه) .
لإغلاق خاصيه التعديل نستخدم :
setEditable(false);
اما للتعامل مع الـ HyperlinkEvent يجب أن نسجل HyperlinkListener للتعامل مع هذا الحدث ، ونعيد تعريف الداله :
public void hyperlinkUpdate(HyperlinkEvent evt)
الان في داخل هذه الداله نضع الكود الذي يتعامل مع الحدث HyperlinkEvent ، هذا الحدث HyperlinkEvent يحتوي على الداله :
public URL getURL( )
والتي من خلالها نستطيع الحصول على الرابط link الذي ولد الحدث ، سواء بالمرور عليه أو بالضغط أو بالخروج من اللنك .
ولكي نعرف نوع الحدث نستخدم الداله :
public HyperlinkEvent.EventType getEventType( )
وهي ترجع ثلاث ثوابت :
HyperlinkEvent.EventType.EXITED
HyperlinkEvent.EventType.ENTERED
HyperlinkEvent.EventType.ACTIVATED
باختصار ، عندما يولد حدث من نوع HyperlinkEvent (سواء بالضغط على اللنك ، أو المرور فيه ) ، سوف يرسل اللنك الى HyperlinkEvent ويتم استدعاء الداله hyperlinkUpdate ، الان في هذه الداله ، أقوم بالحصول على الURL الموجود في HyperlinkEvent باستخدام getURL ، بعدها ، نقوم بمعرفه نوع الحدث ، مثلا اذا كان ACTIVATED (يعني تم الضغط) هنا مثلا نستدعي الداله setPage بالURL وهكذا نكون فتحنا الصفحه الجديده ، مثلا اذا كان نوع الحدث ENTERED (أي تم المرور فيه) نقوم مثلا بطباعه اسم url في status bar ، واذا كان نوع الحدث EXITED (اي تم تحرك الماوس والخروج من اللنك) نقوم بمثلا بمسح وتفريغ status bar .
المثال في المرفقات عباره عن متصفح بسيط غير مكتمل كتبته من فتره ، ولكن التكمله تعتبر gui programming وليس network Programming ، وهذه صوره للبرنامج البسيط :

تقريبا لا يوجد زر يعمل ماعدا Go ، back ، وexit :) ، لكن التكمله فيه تعتمد على معرفتك لـgui كما ذكرت ، ويمكن أن نطوره بعد أن ننتهي من هذه الsession ويكون كمشروع جماعي .
الى هنا ننتهي هذا اليوم ، ونكمل المره القادمه في موضوع جديد وهو صلب برمجه الشبكات الا وهو Server/Client Programming أو ما يعرف بـ Socket Programming ، وباذن الله يكون الموضوع مليئ بالكثير من المعلومات والبرامج أيضا - التكمله حتكون في هذا الموضوع - .
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
سلام عليك يا رومنسي الله ..الله ..الله
لي مناقشة من اجل اخر درس لك ولكن عندي سؤال لبنت اليمن ارجو اجابتي عليه:
رائع ما قدمتيه بما يلي ....
بنت اليمن كتب:الموضوع اليوم جميل جداً ... جزاك الله كل الخيرو هذا حلي للتمرين :
import java.net.URL; import java.net.MalformedURLException; import java.io.PrintWriter; import java.io.IOException; import java.util.Scanner; public class TestURL { public static void main(String[] args) throws MalformedURLException, IOException { Scanner scan = new Scanner(System.in); System.out.println ("Please enter your file's URL: "); URL url = new URL(scan.nextLine()); String path = url.getFile(); String file_name = path.substring(path.lastIndexOf("/") + 1); String file_extension = file_name.substring(file_name.lastIndexOf(".") + 1); scan = new Scanner(url.openStream()); if (( file_extension.compareTo("java") == 0) || ( file_extension.compareTo("html") == 0) || ( file_extension.compareTo("txt") == 0) || ( file_extension.compareTo("cpp") == 0)) { System.out.println ("-------------- Start printing the file on the screen -------------"); while(scan.hasNextLine()) System.out.println (scan.nextLine()); System.out.println ("-------------- End printing the file on the screen -------------"); } else { PrintWriter file = new PrintWriter(file_name); while(scan.hasNextLine()) file.write(scan.nextLine()); System.out.println ("-------------- End printing the file to an external file -------------"); file.close(); } } }سلامي للجميع ،،
ولـــــــــــــكن ....
اذا وضعنا http://localhost/cach/add.php
احظر لنا صفحة add.php
واذا وضعنا
يجب ان ياتي بكل ما داخل مجلد ال cach
من ملفات مخفية وغير مخفية .... حاولت بها لم اصل الى نتيجة
فهل من طريقة للجواب على سؤالي
جلب كل الملفات داخل مجلد محدد ...
أهلا أخي شادو ...
اذا كانت امتداد صفحتك php ، فنحن صممنا البرنامج بحيث يقوم بحفظ الصفحه في الجهاز ، لأن الأمتداد هو php وهو واحد من الأمتدادت الأخرى .
ويكمن أن تضيف هذا الأمتداد مع باقي الأمتدادت المسموحه للعرض (html و cpp ) ، وهكذا سوف يعرض لك كود php كما هو .
اذا وضعنا :
فلن يتعرف برنامجنا البسيط عليه ، لأنه لا يوجد أمتداد ، لذلك الحل الأبسط اضافه / بعد اسم الموقع ، وأختبر هذه العلامه فاذا كانت موجوده في الأخير معناها لا يوجد أمتداد انما صفحه عاديه ، وهنا أعتبرها مثل صفحه html وقم بعرض الكود الخاص بها (كود html ) الخاص بالصفحه .
أنظر لهذا البرنامج ، كتبته ليقوم بالمهمه ، يمكنك اضافه php الى المصفوفه printExt وسوف يعمل تماما .
أيضا المواقع التي تنتهي ب com و net ، يجب أخذ الأعتبار بها .
/*********************** Program Detial ************************************/
// Usge Of Program : java WWRS URL
// Example for URL :
// http://www.google.com
// http://www.msn.com/
// http://www.wajdy.com/romansy.jpg
// http://www.anySite.net/anyFile/song/welecome.mp3
/*********************** END-OF-Detial ************************************/
import java.util.Scanner;
import java.util.StringTokenizer;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.MalformedURLException;
public class WWRS
{
// here extension of normal file ( file that we want to print it in screen)
private static String printExt[] = {"java","c","cpp","html","htm","txt"};
public static void main (String args[]) throws IOException
{
try
{
if ( args.length > 0 )
{
// take the url from command line
String name = args[0];
// Convert to URL object
URL url = new URL(name);
// read Raw Data ( Uniterpreted Data) for URL object
Scanner input = new Scanner ( url.openStream() );
// if file is text File ( cpp , c , html , htm ,java) print it in screen
// else if its media file (image , audio , video) save it in disk
String ext = getExtension ( name, "." ); // get Exteniosn frm URL
// if the file is text print it
if ( isNormalFile(ext) ) // return true if extension is founded in printExt[]
{
// if there is data left , print it
while ( input.hasNext() )
{
System.out.println(input.nextLine()); // print line per line
}
}
else // file is media file
{
saveFileToDisk(url);
}
}
else // args less than 0 , ie no URL
{
System.out.println("Invalid Entering !! Usage : java WWRS URL ");
}
}
catch ( MalformedURLException e) // if URL is invalid
{
System.out.println("Inavlid URL , Try Again !");
}
}
public static boolean isNormalFile (String s)
{
// if the extendsion is HTML , CPP , C , JAVA return true
for (int i=0; i<printExt.length; i++)
if ( s.equals(printExt) )
return true;
// now maybe file has not extension ( i.e http://www.google.com )
// if the string end with .com .net or end with /
if ( s.endsWith("/") || s.endsWith(".com"))
return true;
// here file is media file and must be saved
return false;
}
public static String getExtension (String path , String e)
{
StringTokenizer token = new StringTokenizer(path, e);
// take the last word in url ( after . )
String str = "";
while ( token.hasMoreTokens() )
str = token.nextToken();
return str;
}
public static void saveFileToDisk (URL u) throws IOException
{
String ext = getExtension(u.getFile(),"/"); // get file Name
System.out.print("\n\nDo You Want To Download " + ext);
System.out.print(" (Y|N) : " );
Scanner input = new Scanner(System.in);
String ans = input.nextLine(); // take answer from keyboard
if ( ans.equals("Y") || ans.equals("y") )
{
// make new File in disk , name the new file as name the file in url
FileOutputStream outFile = new FileOutputStream(ext);
// getContent of URL ( Uniterpreted Data)
InputStream in = u.openStream();
// now read from inputStream and put data in file
int c=0;
while ( (c=in.read()) != -1 )
outFile.write( (byte)c);
outFile.close();
System.out.println("Saving Complete .... ");
}
}
}تذكر حاليا ، نحن فقط نريد عرض raw data ، وليس عرض المحتويات بالشكل الطبيعي ، , ويمكنك أن تقرأ الدرس الأخير لعرض المحتويات كما هي .
أي سؤال ؟
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
رائع يا صديقي .. ولكن
عندما نفذت البرنامج السابق ووضعت ما يلي
حفظ لي الصفحة المطلوبة
وعندما كتبت
حفظ لي ملف باسم cach لا ادري ما امتداده
وعندما كتبت
اضهر لي فعلا كود html كما تفضلت حظرتك
ولكن انا مجلدي ال cach المتوضع على السيرفر يحوي العديد من صفحات الويب بالاضافة الى الصور و الاغاني
فاي كود احظر لي ولاي صفحة ويب وجودة بالمجلد ....؟؟؟؟
كل ما اقصده .. تخيل بان نحول البرنامج السابق الى برنامج حفظ صفحات الانترنت اي تمرق له المجلد المتوقع ان تكون به الصفحات والملفات والبرامج المراد تخزينها والبرنامج يقوم بعملية الحفظ للمجلد السوبر الذي يحوي كل ما يحويه ولا يهمنا ما يحوي.....
اريد ان اتي بالمجلد الاب كما هوا مجلد بما يحويه فكيف ...
أهلا شادوو ،
بالنسبه للبرنامج البسيط الذي كتبناه ، كان الغرض منه فقط ، هو الوصول الى صفحه معينه في السيرفر ، وبعدها أقارن أمتداد هذه الصفحه بمجموعه من الأمتدادات المسموحه (html , cpp ) فاذا كان الأمتداد هو واحد منهم أقوم بأخذ محتويات الصفحه وأعرضها في الشاشه ، وفي حال كان الأمتداد غير ذلك (امتداد أخر ) سوف يقوم بحفظ المحتويات في ملف باسم الملف الموجود في url .
لكن اذا كان الـ url بهذا الشكل :
فلن يجد أمتداد هذه الصفحه من ضمن الأمتدادات المسموحه لذلك سوف يقوم بحفظ هذه الصفحه في الجهاز .
لذلك كان الحل أني دائما عندما أدخل اسم موقع بدون ملف معين ، أقوم بوضع علامه / بعد اسم الموقع ، وأجعل هذه العلامه / مع الأمتدادت المسموحه .
اي في حال أنتهي url بأحد الأمتدادات المسموحه أو أنتهي ب / ، فقم عرض المحتويات على الشاشه ، وهكذا أنهينا هذه المشكله . (أنظر للكود الذي كتبته المشاركه السابقه ، وستجد أنه عالج تلك المشكله) .
بالنسبه للصفحه php ، نحن أصلا كنا نريد حفظها على الجهاز ، لكن بما أنك تريد عرضها على الشاشه ، فقم بوضع اسم php في المصفوفه في البرنامج السابق ، وأي امتداد أخر تريد عرضه ضعه في المصفوفه printExt ،
بالنسبه لما تريده ، وهو أرسال كافه المحتويات ، فبطريقتنا التي استخدمناها يجب أن أعرف أسم الملف المحدد وبعدها أقوم بأخذ محتوياته عن طريق openStream ، أما اذا كان مجلد فـ openStream الناتج منها هو فقط أسماء الملفات الموجوده في المجلد ويأتيك في صوره html ،
يمكن أن نفعل ما تريد ، عن طريق عمل prase للناتج السابق ، ونحصل على جميع أسماء الملفات في السيرفر ، ونعمل url لكل اسم ملف في السيرفر ، ونخرج محتوياته openstream . طبعا الموضوع طويل ، اضافه الى ذلك نحن لم نتناول موضوع الhtml Parsing .
والحل الأخر عن طريق عمل socket بين الكلاينت والسيرفر ومنه أستطيع الارسال والأستقبال بسهوله ، ولكن أيضا نحن لم نتناول هذا الموضوع :)
URLConnection
HTTPConnection
(ذكرت في أول الموضوع أننا سنتناول في Session 2 ، وخاصه بعد أن ننهي موضوع client/Server ، حتى تكون لنا قاعده قويه نمشي عليها ) .
لذلك يمكن أن تأجل سؤالك ، الى بضعه مواضيع قادمه ، وحينها ستدرك الجواب من نفسك :) .
بالتوفيق .
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
السلام عليكم ...
طبعاً لا استطيع الا ان اشكرك اخي رومنسي على هذا الموضوع اكثر فأكثر :) جزاك الله خير الجزاء ..
حالياً (و لأنك ما عملت لنا واجب :D ) فأنا اعمل على عمل براوزر خاص بي كمشروع تدريبي لي ..
قمت بإنزال المثال المرفق ..
و كمثال تدريبي عملت كود يطبع لي اللنك الذي يضغط عليه الماوس كرسالة ثم ينتقل الى الصفحة المطلوبة.
import javax.swing.JFrame;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import java.io.IOException;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.JOptionPane;
public class TestEditPane extends JFrame implements HyperlinkListener{
JEditorPane jep = new JEditorPane();
TestEditPane()
{
super("Local Host");
try
{
jep.setEditable(false);
jep.addHyperlinkListener(this);
jep.setPage("http://localhost");
}
catch(IOException e){
}
getContentPane().add(new JScrollPane(jep));
setSize(500,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args)
{
new TestEditPane();
}
public void hyperlinkUpdate(HyperlinkEvent e)
{
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
{
String url = e.getURL().toString();
JOptionPane.showMessageDialog(null, "You Will Go To: " + url);
try{
jep.setPage(url);
}
catch(IOException ee){
}
}
}
}الموضوع مشي حتى لمن اكون اون لاين و اطلب صفحة ...
المسألة فقط في ان شكل الصفحة ما يكون تمام 100% فهل في اشياء اعملها على اساس اعمل مستعرض متقدم و دقيق ؟؟؟
الاخ الكريم shadooo
اقتباسكل ما اقصده .. تخيل بان نحول البرنامج السابق الى برنامج حفظ صفحات الانترنت اي تمرق له المجلد المتوقع ان تكون به الصفحات والملفات والبرامج المراد تخزينها والبرنامج يقوم بعملية الحفظ للمجلد السوبر الذي يحوي كل ما يحويه ولا يهمنا ما يحوي.....اريد ان اتي بالمجلد الاب كما هوا مجلد بما يحويه فكيف ...
فكرة جميلة فعلاً ... !! ممكن نشتغل عليها ...
في الحقيقة انا كنت اظنك تفكر في شيء اخر ...
انت تعرف انو ملفات الـ php كـ server side technology مش ممكن نعرف محتواها .. لكن نعرف ما ينتج عنها على شكل html file ... الفكرة اللي خطرت لي من تساؤلاتك ان نصل الى ملف الـ php نفسة لقراءة محتوياته !!! ممكن نعرف الاكواد المستخدمة ... و كلمة المرور و تفاصيل ممكن تساعد على الخير و الشكر كمان !!! ما ادري هل الفكرة معقولة ؟؟؟
سلامي للجميع ...
لا اله الا الله .. محمد رسول الله
(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)
يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين
بنت اليمن كتب:الفكرة اللي خطرت لي من تساؤلاتك ان نصل الى ملف الـ php نفسة لقراءة محتوياته !!! ممكن نعرف الاكواد المستخدمة ... و كلمة المرور و تفاصيل ممكن تساعد على الخير و الشكر كمان !!! ما ادري هل الفكرة معقولة ؟؟؟
اكثر من معقولة ولما لا .... لكن لننتضر الاخ رومنسي ولينتهي من دروسه لنقوم بتفيذ مشاريع تعبر عن افكارنا ....
الله معكم
السلام عليكم ورحمه الله وبركاته ،
ها قد وصلنا ما كنا نريده من البدايه وهو الجزء الممتع حقيقه في برمجه الشبكات، وهو موضوع Client/Server Programming ، فهذه النوعيه من البرامج أنتشرت بشده في الأونه الأخيره ، حيث يقوم السيرفر (الخادم) بتقديم خدمه ما لكل من يتصل بهذا السيرفر ، ويقوم الكلاينت (العميل) بالأتصال بهذا الخادم لطلب الخدمه المعينه . هذه الخدمه تكون على حسب ما نريد ، يمكن أن تكون أرسال صفحه انترنت كما في http Server ، أو يمكن أن تكون ملف ما يطلبه الكلاينت أو استقبال ملف كما في FTP Server ، أو يمكن أن نرسل التاريخ والوقت Day Time Server ، أو يمكن أن نرسل فيديو يختاره الكلاينت لكي يشاهده ، أو يقوم بارجاع نتجيه استعلام من قاعده البيانات ، أو أي خدمه نريد حتى لو كانت أله حاسبه .
بعض الأحيان يطلق على النوع أيضا Socket Programming ، لأننا حقيقه سوف نتعامل مع socket وهي الأداه التي تسمح لنا بالأتصال والأرسال والأستقبال . ويمكن انشاء نوعين من الـ Socket ، الأول TCP Socket وهنا يكون الأتصال موجه Connection Orinted أي يكون هناك أتصال بمجرد أن أطلبه وسواء كان عمليه ارسال أو لم تكن فالأتصال يكون موجود الى أن اغلقه صراحه ، أضافه على ذلك هذا البرتوكول TCP يتحقق من أن الرساله وصلت بشكل صحيح ، وفي حال لم تصل يقوم باعاده أرسالها مره أخرى . النوع الثاني وهو UDP Socket وهو غير موجه Connectionless وهنا لا يكون هناك أتصال الا في حاله الأرسال أو الأستقبال فقط ، وبرتوكول UDP لا يتحقق من عمليه الأرسال وهو أسرع من الـ TCP لهذا السبب . (لن نسهب كثيرا في الجزء النظري ، ومن أراد معرفه ما يجري بالضبط ، فيمكن أن نضع عده روابط مفيده تتعمق في الموضوع ).
موضوعنا اليوم سيكون عن TCP Socket ، وقبل أن نبدأ في عرض الكلاسات الرئيسيه والدوال المستخدمه ، سنبدأ بتوضيح الخطوات التي يجب أن نتبعها لبرمجه الخادم والعميل ، فهذه الخطوات تكاد تكون ثابته في أي برنامج من هذا النوع . سنقوم بشرحها بشكل سريع الأن ، وسوف تتضح عندما نتقدم أكثر باذن الله .
الخطوات الرئيسيه بالنسبه للسيرفر Server :
1- فتح بورت معين في السيرفر لكي يتصل عن طريقه الكلاينت ، وهنا سوف نستخدم الكلاس ServerSocket وهو خاص بالسيرفر :
ServerSocket serverSocket = new ServerSocket(5000);
لاحظ أننا أخترنا رقم البورت 5000 ، وهناك 65535 بورت أستطيع أستخدام أي واحد منهم ، لكن يفضل دائما الأختيار من البورتات من 1024 الى 65535 ، لأن البورتات من 0 الى 1023 تكون محجوزه للخدمات الموجوده في الجهاز .
2- بعد فتح المنفذ ، يكون السيرفر في حاله أستماع Listing أي منتظر أي طلب للأتصال . في حال تم الأتصال به (اي قام كلاينت بالأتصال به) ، فيقوم بعمل accept لهذا الكلاينت ، ويتم عمل accpet عن طريق الكائن من نوع ServerSocket والذي عن طريقه فتحنا به المنفذ في الخطوه الأولى . الأن عندما أعمل قبول لهذا الكلاينت ، فالناتج من هذه العمليه هو Socket ، وعن طريقه أستطيع أرسل وأستقبل للكلاينت :
Socket socket = serverSocket.accpet();
لاحظ أن في أثناء فتره الأنتظار يكون السيرفر في حاله Block ، الى أن يحصل أتصال .
3- بعدما حصلنا على socket ، كل ما علينا من خلال هذا السوكت أن أقوم بتجهيز الـ Stream لكي أقوم بالقرائه والكتابه في السوكت(أي لكي أرسل وأستقبل للكلاينت ) . وسوف أستخدم الدوال (وهي موجوده في الكلاس Socket ) :
InputStream getInputStream (); OutputStream getOutputStream();
لاحظ أن الداله الأولى ترجع كائن من نوع InputStream ، وهنا أستطيع أستخدام أي كلاس وراث من هذا الكلاس ، مثلا DataInputStream أو مثلا Scanner ، أو مثلا ObjectInputStream .
أيضا الداله الثانيه ترجع OuptutStream ، وهنا نستخدم مثلا DataOutputStream أو مثلا PrintWriter أو مثلا ObjectOutputStream .
Scanner input = new Scanner ( socket.getInputStream() ); PrintWriter output = new PrintWriter ( socket.getOutputStream() , true);
هنا أصبح Input جاهز للقرائه من السوكت ( البيانات القادمه من الكلاينت ) ، و output جاهز للكتابه في السوكت (البيانات المرسله للكلاينت) .
بعدها نقوم بالأرسال والأستقبال ، على حسب ما نريد .
msgIn = input.nextLine(); output.println(msgOut);
5- أخيرا ، نقوم باغلاق السوكت close ، لاحظ أن لدينا :
serverSocket و socket ، فاذا أغلقنا الأول فنكون قد أغلقنا السيرفر واذا أغلقنا الثاني فنكون قد أغلقنا الكلاينت ، وبشكل عام السيرفر يجب أن يكون له Hight Availabiltiy أي يكون متصل بشكل دائم ، لذلك لن نقوم باغلاقه أبدا .
هذه الخطوات الرئيسيه للسيرفر ، وسوف نقوم بالتفصيل أكثر بعد قليل . بالنسبه للخطوات الرئيسيه في الكلاينت فهي :
1- طلب الأتصال من السيرفر ، ويكون ذلك عن طريق عمل Socket بعنوان السيرفر ، ورقم البورت الذي أريد الأتصال به ،
Socket socket = new Socket("127.0.0.1",5000);و يمكن أن أرسل العنوان ك String ، أو أرسله ك InetAddress .
بعدما أقوم بطلب الأتصال ، ويقوم السيرفر بعمل accpet لي (الكلاينت) أقوم بتجهيز الStream للقرائه والكتابه في السوكت ، وهي بنفس الخطوه 3 في السيرفر .
أخيرا نقوم باغلاق الكلاينت (socket) .
وهكذا أنتهت العمليه وأصبحت مبرمج شبكات محترف :) :) .
نعيد ذكر الكلاسات الرئيسيه التي سوف نستخدمها مع توضيح الـ Exception والدوال الرئيسيه الموجوده بكل كلاس ، مع بعض الأمثله :
الدوال في الكلاس ServerSocket هي (وكما ذكرنا يستخدم هذا الكلاس في السيرفر فقط) :
public ServerSocket(int port) throws IOException public Socket accept( ) throws IOException public void close( ) throws IOException public InetAddress getInetAddress( ) public int getLocalPort( )
الداله الأولى وهي داله بناء وهناك أكثر من داله بناء لـ ServerSocket ، لكن هذه هي المستخدمه بشكل أكبر :
public ServerSocket(int port) throws IOException
لاحظ هنا أنه يحصل exception عندما نقوم بفتح بورت مفتوح مسبقا من قبل برنامج أخر وفي هذه الحاله سوف يحصل exception من نوع IOException .
يمكن الأن أن تكتب برنامج لكي يختبر هل البورت الفلاني مفتوح أم لا في السيرفر ، فاذا كان مفتوح فسوف ينفذ الـ IOException :
// Simple Local Port Scanner
import java.net.ServerSocket;
import java.io.IOException;
public class Demo
{
public static void main (String args[])
{
for ( int i=1; i<=1024; i++)
{
try
{
ServerSocket serverSocket = new ServerSocket(i);
serverSocket.close();
}
catch ( IOException e)
{
System.out.println("There is a Server on Port : " + i);
}
}
}
}تنفيذ البرنامج :
java Demo
There is a Server on Port : 80
There is a Server on Port : 135
There is a Server on Port : 445
الداله الثانيه وهي :
public Socket accept( ) throws IOException
وهي تستخدم كما ذكرنا لقبول اتصال من الكلاينت ، وترجع socket وهذا السوكت يحتوي على معلومات الكلاينت الذي اتصل مثل عنوانه حتى نستطيع ارسال البيانات اليه .
كما ذكرنا أن السيرفر أساسا وقبل أتصال أي كلاينت يكون في حاله أستماع ، أي لن يتنفذ أي كود بعد سطر accept الا عندما يتصل client بعدها يكمل التنفيذ . لذلك يجب أن نفصل هذا الكود من الواجهه gui بأي طريقه ، والا سيكون البرنامج أو الواجهه في حاله hang الى أن يتصل بها كلاينت ما . سوف نشاهد مثال على ذلك بعد قليل .
الداله الثالثه :
public void close( ) throws IOException
وهي لاغلاق السوكت ServerSocket ، وكما ذكرنا نادرا ما نريد اغلاق السيرفر . لاحظ أن هذه الداله تولد exception في حال لم نستطع اغلاق السيرفر .
الدوال التاليه ، ويتضح عملها من اسم الداله :
public InetAddress getInetAddress( ) public int getLocalPort( )
الأولى ترجع عنوان السيرفر ، والثانيه البورت ، ولن نستخدم هذه الدوال في غالب البرامج ، لأننا على علم بالبورت والعنوان أيضا .
الدوال في الكلاس Socket (وهو يستخدم في السيرفر والكلاينت ، للارسال والأستقبال ) :
public Socket(String host, int port) throws UnknownHostException, IOException public Socket(InetAddress host, int port) throws IOException public InetAddress getInetAddress( ) public InetAddress getLocalAddress( ) public int getPort( ) public int getLocalPort( ) public InputStream getInputStream( ) throws IOException public OutputStream getOutputStream( ) throws IOException public void close( ) throws IOException
الداله الاولى وهي داله بناء :
public Socket(String host, int port) throws UnknownHostException, IOException
وهي تقوم بطلب الأتصال من الhost من خلال البورت port المحدد ، ويحدث هنا exception من نوع UnknownHostException في حالة كان اسم host خاطئ ، ويحدث IOException في حاله لم يقبل not accpet السيرفر طلب الأتصال ، أو في حال أنقطع خط الأتصال فصل السلك مثلا . ويكمن أن نقوم بعمل catch لكل من هذه الـ Exception ، الcatch الأول ل UnknownHostException والثاني ل IOException ، ولن نستطيع عمل العكس وذلك لأن IOException هو الكلاس الأب UnknownHostException ومن قواعد الجافا أننا لن نستطيع عمل catch لاب ومن ثم أبن ، لذلك نراعي الترتيب الأبناء أولا ثم الأباء . أو يمكن أن نقوم بعمل catch للأب فقط IOException .
باستخدام داله البناء هذه ، نقوم بعمل ماسح للبورتات لأي سيرفر نريد ، وفي حال حصلنا على exception نعرف أن البورت مغلق وفي حال لم يحصل نعرف أن هناك بورت في السيرفر .
(لاحظ بطئ البرنامج التالي ، مقارنه مع المثال الأول والخاص بـ local Port Scanner ، والسبب هو أننا هنا نقوم بطلب أتصال لكل بورت ) .
// Simple Remote Port Scanner
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.IOException;
public class Demo
{
public static void main (String args[])
{
String host = "localHost";
if ( args.length > 0 )
host = args[0];
for (int i=1; i<=1024; i++)
{
try
{
Socket socket = new Socket(host,i);
System.out.println("There is Server in Port : " + i + " in " + host );
socket.close();
}
catch ( UnknownHostException e)
{
System.out.println(e);
break;
}
catch ( IOException e)
{ }
}
}
}java Demo
There is Server in Port : 80 in localHost
There is Server in Port : 135 in localHost
الدوال التاليه وتستخدم لعرض معلومات السوكت :
public InetAddress getInetAddress( ) public InetAddress getLocalAddress( ) public int getPort( ) public int getLocalPort( )
الداله الأولى وتقوم بعرض عنوان الجهه الأخرى للأتصال .
الداله الثانيه وتقوم بعرض العنوان الحالي .
الداله الثالثه وتقوم بعرض بورت الجهه الأخرى .
الداله الرابعه وتقوم بعرض البورت الحالي .
مثال لاستخدام هذه الدوال :
//Get a socket's information
import java.net.Socket;
import java.io.IOException;
public class Demo
{
public static void main (String args[])
{
try
{
Socket socket = new Socket("127.0.0.1",80);
System.out.println("Conntected To : " + socket.getInetAddress() + "\n" +
"on Port : " + socket.getPort() + "\n\n" +
"From : " + socket.getLocalAddress() + "\n" +
"on Port : " + socket.getLocalPort());
}
catch ( IOException e)
{
e.printStackTrace();
}
}
}المخرج :
java Demo
Conntected To : localhost/127.0.0.1
on Port : 80
From : /127.0.0.1
on Port : 2297
قم بتشغيل البرنامج عده مرات ، وسوف تلاحظ أن البورت الحالي للكلاينت يختلف كل مره ، لأن القيمه يتم أختيارها وقت التشغيل . أي أن البورت الحالي للكلاينت لا تقوم أنت باختياره .
أخر دوال في الكلاس Socket :
public InputStream getInputStream( ) throws IOException public OutputStream getOutputStream( ) throws IOException public void close( ) throws IOException
الداله الأولى ترجع input Stream للقرائه من السوكت الى البرنامج ،وهنا يمكن أن نمرر chain هذا الInputStream الى أحد الكلاسات التاليه :
DataInputStream أو InputStreamReader ولأداء أفضل BufferedInputStream و BufferedReader ، أو يمكن استخدام Scanner أيضا .
الداله الثانيه وهي ترجع OutputStream للكتابه من البرنامج الى السوكت ، وهنا يكمن أن نمرر هذه OuputStream لأحد الكلاسات التاليه :
DataOutputStream أو OutputStreamWriter أو PrintWriter وهو ما أفضله .
الداله الثالثه وهي لأغلاق السوكت . وعاده ما يتم اختبار السوكت قبل اغلاقه :
if ( socket != null ) socket.close();
لاحظ جميع الدوال السابقه تولد IOException لذلك يجب أن تكون ضمن try-catch Block .
نبدا الأن في الأمثله ، على بركه الله ...
ملاحظه :
يمكنك تجربه البرامج الحاليه ، بدون الحاجه الى وجود شبكه وجهاز كلاينت وسيرفر ، كل ما عليك هو تشغيل البرنامجين مع بعض (السيرفر أولا ، ثم الكلاينت ) . وفي حال أردت تجربه البرنامجين في شبكه ما ، قم بتغير العنوان في برنامج الكلاينت عند انشاء السوكت الى العنوان الذي تريد . (في أمثلتنا الحاليه سنضع العنوان 127.0.0.1 ، لأننا نجرب السيرفر والكلاينت على نفس الجهاز) .
المثال الأول ، وهو لعمل سيرفر يستقبل جمله String من الكلاينت ويطبعها لديه ، ومن ثم يرسل Ok للكلاينت للدلاله على استلام الرسال ، وتكرر هذه العمليه الى أن يدخل الكلاينت CLOSE . وفي هذه الحاله يجب أن نقوم في السيرفر باغلاق السوكت الخاص بالكلاينت ،وفي الكلاينت نقوم باغلاق السوكت أيضا .
السيرفر :
// TCPEchoServer
// Received Message From User And send ok to client
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class TCPEchoServer
{
private static final int PORT = 5000;
private static ServerSocket serverSocket;
private static Socket socket;
public static void main (String args[])
{
try
{
serverSocket = new ServerSocket(PORT);
System.out.println("********** Server Open Connnection **********");
}
catch ( IOException e)
{
System.out.println("Unable to Attach To Port !");
System.exit(1);
}
while ( true )
accessClient();
}
public static void accessClient()
{
try
{
socket = serverSocket.accept();
Scanner input = new Scanner ( socket.getInputStream() );
PrintWriter output = new PrintWriter( socket.getOutputStream() , true );
String msgIn , msgOut;
msgIn = input.nextLine();
while ( ! msgIn.equals("CLOSE") )
{
System.out.println("Client > " + msgIn );
msgOut = " OK ";
output.println(msgOut);
msgIn = input.nextLine();
}
}
catch ( IOException e)
{ e.printStackTrace(); }
finally
{
try
{
if ( socket != null )
socket.close();
System.out.println("Server Close Client Connection !");
}
catch ( IOException e)
{
System.out.println("Cannot Disconnect Client !");
System.exit(1);
}
}
}
}الكلاينت :
// TCPEchoClient
// send Message to Server , Received OK Message
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.Socket;
import java.io.PrintWriter;
import java.util.Scanner;
import java.io.IOException;
public class TCPEchoClient
{
private static final int PORT = 5000;
private static Socket socket;
private static InetAddress address;
public static void main (String args[])
{
try
{
address = InetAddress.getLocalHost();
}
catch (UnknownHostException e)
{
System.out.println("Cannot Find IP Number !");
}
accessServer();
}
public static void accessServer ()
{
try
{
socket = new Socket(address,PORT);
Scanner input = new Scanner( socket.getInputStream() );
PrintWriter output = new PrintWriter( socket.getOutputStream() , true );
String msgIn = "" , msgOut = "";
Scanner uInput = new Scanner( System.in);
while ( ! msgOut.equals("CLOSE") )
{
System.out.print("Enter Message : " );
msgOut = uInput.nextLine();
output.println(msgOut);
if ( !msgOut.equals("CLOSE"))
{
msgIn = input.nextLine();
System.out.println("Server > " + msgIn );
}
}
}
catch ( IOException e)
{ e.printStackTrace();}
finally
{
try
{
if ( socket != null )
socket.close();
System.out.println("Clinet Close Connection !");
}
catch ( IOException e)
{
System.out.println("Cannot Disconnect Client !");
System.exit(1);
}
}
}
}لاحظ في السيرفر ، أننا نريد أن ننفذ السيرفر بشكل دائم ، لذلك كتبنا :
while ( true ) accessClient();
وهكذا سوف يكون السيرفر في حال عمل مستمر ، وكل مره يستدعي الداله accessClient ، وفي بدايه هذه الداله سوف ينتظر أي طلب أتصال من أي كلاينت ، في حال لم يأتيه سوف يكون البرنامج معلق block في هذا السطر الى أن يأتيه أتصال ، أو تقوم بغلق البرنامج يدويا وذلك بالضغط على CTRL + C .
في حال هناك كلاينت طلب الأتصال ، سوف نكمل باقي الكود في الداله accessClient ، وقمنا في البدايه بتجهيز Input و output للقرائه والكتابه من السوكت ، بعدها وهي أول خطوه وهي أستقبال الرساله القادمه من الكلاينت :
msgIn = input.nextLine();
بعدها نقارن هذه الرساله بـ CLOSE ، فاذا تساوت خرجنا من الحلقه while ونفذنا تكمله الكود وهو هنا الجزء finally وهو غلق السوكت الخاص بالكلاينت ، أي يتم اغلاق الأتصال مع الكلاينت في حال أرسل الكلاينت كلمه CLOSE.
في حال أرسل الكلاينت أي جمله أخرى ، سيتحقق الشرط في while ، وهنا يدخل جسم هذه الحلقه ، وسوف يطبع هذه الرساله ، ويقوم بارساله OK الى الكلاينت . وسوف سيتمر هكذا الى أن يرسل الكلاينت CLOSE .
في حال أرسل الكلاينت CLOSE وقمنا باغلاق السوكت ، سوف يرجع الى الحلقه في الداله main وهي حلقه كما ذكرنا مستمره بشكل دائم ، وسوف يستدعي الداله accessClient مره أخرى ، وينتظر اتصال أخر ، وهكذا .... ويكمن أغلاق البرنامج بالضغط على CTRL + C .
أخر ملاحظه ، وهي أن البرنامج السابق لا يتعامل في نفس اللحظه الا مع كلاينت واحد فقط . في حال أردنا أن نتعامل مع أكثر من كلاينت في نفس اللحظه MutliClient يجب أن نستخدم الـ Thread في السيرفر ، أو نستخدم التقنيه المسماه بـ Non Blocking Server ، وهي تعتمد على مفهوم القنوات Channels بدلا من الStream ، وسوف نتحدث عنها المره القادمه بمشيئه الله .
الان عند تشغيلك للسيرفر أولا ، سوف تلاحظ أن السيرفر طبع جمله :
اقتباس********** Server Open Connnection **********
وهو يدل على أنه تم فتح البورت في السيرفر ، وأنه الأن في حاله انتظار أو أستماع ، وسوف يكون بهذا الشكل الى أن تقوم بتشغيل الكلاينت ...
الان قم بتشغيل الكلاينت ، وسوف تطبع لك جمله Enter Message ، وبعدها أبدا في الأدخال ....
وهذه المخرجات :
في السيرفر :
java TCPEchoServer
********** Server Open Connnection **********
Client > wajdy essam
Client > ArabTeam2000
Server Close Client Connection !
في الكلاينت :
java TCPEchoClient
Enter Message : wajdy essam
Server > OK
Enter Message : ArabTeam2000
Server > OK
Enter Message : CLOSE
Clinet Close Connection !
المثال التالي وهو بالمرفقات ، لعمل DayTime Server ، وهنا السيرفر يقدم خدمه التاريخ والوقت لأي كلاينت يتصل به .أي عندما يقوم الكلاينت بالأتصال يقوم السيرفر مباشره بارسال التاريخ اليه . والكلاينت لن يرسل ولا أي معلومه . (لاحظ هنا أن السيرفر هو أول من يقوم بالارسال ، بعكس برنامج echo والذي كان الكلاينت هو الذي يرسل أولا والسيرفر يستقبل ). طبعا عمليه من يرسل أو يستقبل أولا تقوم بتحديدها أنت المبرمج أو على حسب المتطلب .
وهذه صوره للبرنامج :

والبرنامج بسيط خاصه لمن فهم البرنامج الأول . فقط الفرق هو أننا في السيرفر سنرسل التاريخ والوقت بدلا من رساله OK كما في البرنامج الأول .
المثال التالي وهو port Scanner في المرفقات (وقد تم شرح هذا البرنامج في بدايه هذا الدرس) ولكن الأختلاف هنا هي الواجهه فقط ، وهو لعمل سكان على البورتات في الجهاز المحلي ، وسوف تستغرب أننا عملنا بالسوكت العادي ، أي أننا سوف نتصل كل مره بالسيرفر ، مما يبطئ البرنامج . طبعا يمكن عمله ب ServerSocket مباشره .
وهذه صوره له :

الى هنا أصبحنا نستطيع ارسال أي رساله أو رقم أو حتى تاريخ (نحوله الى string ونرسله) ، لكن كيف يمكن أن نرسل ملف ، أو صوره ، أو ملف فيديو ، أو حتى مجلد كامل ...
أفضل طريقه هي أرسال محتويات هذه الملفات (سواء صوره أو صوت أو فيديو) ك Object ، وذلك من خلال :
ObjectOutputStream و قرائتها كObject من خلال ObjectInputStream .
هنا سوف نجهز عمليه الكتابه في السوكت من خلال out .
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
الان عن طريق الداله write نستطيع ارسال المحتويات التي نمررها لهذه الداله ، والشرط الوحيد هنا أن هذه المحتويات يجب أن تكون من نوع بايت :
out.writeObject(array);
لذلك لارسال مثلا ملف a.mp3 نقوم أولا بفتح هذا الملف ، وقرائه محتوياته في مصفوفه من نوع بايت ونقوم بارسالها .
FileInputStream in = new FileInputStream(name); int size = (int) ( (new File(name)).length()); byte array[] = new byte[size]; in.read(array); // here we read from file and store content in array in.close(); // close the file out.writeObject(array); // send the array of byte , content of file out.flush(); // flush the output stream
طبعا الطريقه السابقه ، لأرسال أي ملف name مهما كان نوعه ، صوره ، ملف عادي ، فيديو ، ملف exe الخ .
الأن للقرائه ، سأقرأ الرساله القادمه كاObject وأخزنها في مصفوفه من نوع byte ، وأفتح ملف للكتابه بأي أسم ، وعاده يفضل باسم الملف نفسه الذي أرسلته الجهه الأخرى ، وأقوم بعدها بحفظ المحتويات في الملف واغلاق الملف .
byte array[] = (byte[]) in.readObject();
FileOutputStream file = null;
if ( name.equals("image") )
file = new FileOutputStream("newImage.jpg");
else if ( name.equals("sound") )
file = new FileOutputStream("newSound.mp3");
file.write(array);
file.close();وهذا مثال بسيط للارسال صوره أو صوت ، ويقوم الكلاينت بادخال ما يريد sound أو image أو close ، في حال أدخل الكلاينت sound يقوم السيرفر بارسال محتويات ملف a.mp3 ، وفي حال أدخل image يقوم السيرفر بارسال محتويات i26.jpg وفي حال أدخل الكلاينت close فيقوم السيرفر بغلق السوكت الخاص بالكلاينت . طبعا عليك أن تغير اسماء هذه الصور باي صوره من جهازك ، ضعها في نفس المسار . -البرنامج ليست فيه خاصيه اختيار الصوره أو الملف ، ولذلك لغرض التبسيط فقط-
وهذا الكود الخاص بالسيرفر :
// Server That Send Media (Image , Sound , Video ) to Cleint
import java.net.ServerSocket;
import java.net.Socket;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.ObjectOutputStream;
import java.io.File;
import java.util.Scanner;
public class Server
{
private static ServerSocket serverSocket;
private static Socket socket;
private static final int PORT = 7000;
public static void main (String args[])
{
try
{
serverSocket = new ServerSocket(PORT);
System.out.println("***** Server Open Connection *******");
}
catch ( IOException e)
{
System.out.println("Unable to Open Port !");
System.exit(1);
}
while (true )
handleClient();
}
public static void handleClient()
{
Scanner input = null;
String msg = "";
try
{
socket = serverSocket.accept();
System.out.println("new Client Connection With Server !");
System.out.println("Client Info : " + socket.toString() +"\n");
input = new Scanner(socket.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
msg = input.nextLine();
if ( msg.equals("image") || msg.equals("sound") )
{
System.out.println("Cleint Request Download : " + msg );
if ( msg.equals("image") )
sendFile(out,"i26.jpg");
if ( msg.equals("sound") )
sendFile(out,"a.mp3");
}
}
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
System.exit(1);
}
}
public static void sendFile ( ObjectOutputStream out ,String name) throws ClassNotFoundException , IOException
{
FileInputStream in = new FileInputStream(name);
int size = (int) ( (new File(name)).length());
byte array[] = new byte[size];
in.read(array);
in.close();
out.writeObject(array);
out.flush();
}
}
أما الكلاينت :
// Received Media From Server
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.util.Scanner;
public class Client
{
private static Socket socket;
private static InetAddress address;
private static final int PORT = 7000;
public static void main (String arsg[])
{
try
{
address = InetAddress.getLocalHost();
}
catch (UnknownHostException e)
{
System.out.println("Cannot find Id Host !");
System.exit(1);
}
accessServer();
}
public static void accessServer ()
{
PrintWriter output = null;
Scanner input = null;
ObjectInputStream objIn = null;
try
{
socket = new Socket(address,PORT);
output = new PrintWriter(socket.getOutputStream(),true);
objIn = new ObjectInputStream(socket.getInputStream());
}
catch (IOException e)
{
e.printStackTrace();
System.exit(1);
}
try
{
String msg = "";
input = new Scanner(System.in);
System.out.println("Available Service is : ['Image','sound'] 'exit' for close\n\n");
System.out.println("Enter Name Of Service You Want : " );
msg = input.nextLine();
output.println(msg);
getFile(objIn,msg);
socket.close();
}
catch ( IOException e)
{
e.printStackTrace();
System.exit(1);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
System.exit(1);
}
}
public static void getFile (ObjectInputStream in , String name) throws ClassNotFoundException , IOException
{
byte array[] = (byte[]) in.readObject();
FileOutputStream file = null;
if ( name.equals("image") )
file = new FileOutputStream("newImage.jpg");
else if ( name.equals("sound") )
file = new FileOutputStream("newSound.mp3");
file.write(array);
file.close();
}
}
Mutlithreaded Server
================
جميع البرامج السابقه ، تدعم كلاينت واحد في اللحظه ، ولن يستطيع السيرفر التعامل مع أكثر من كلاينت واحد في نفس اللحظه ، وطبعا هذا أمر غير عملي ، حيث على السيرفر التعامل مع أكثر من كلاينت في نفس اللحظه ، وهنا يمكن أن نستخدم طريقتين :
1- تعتمد على استخدام Thread
2- تعتمد على استخدام تقنيه Non Blocking Server وهي جائت في JDK 1.4 وسوف نتناولها المره المقبله ان شاء الله .
الان سوف نتناول الطريقه الأولى وهي باستخدام الـ Thread . وهنا البرنامج لن يتغير أبدا ما عدا أضافه سطرين فقط في السيرفر أما الكلاينت فكما هو .
كل ما علينا في السيرفر أننا بعد عمل accpet لكلاينت ما لن نقوم بالتعامل معه مباشره ، بل نقوم بتمرير هذا السوكت الى Thread ونقوم بتشغيل هذا الThread . (ومن داخل الـ Thread يتم التعامل مع الكلاينت ) .
وفي كل مره يتصل كلاينت نقوم بانشاء Thread وهكذا ... أي أصبح لدينا Multithreaded Server يتعامل مع أكثر من كلاينت ، والمثال القادم هو نفس مثال echo ولكن باستخدام الـ thread لكي يتم التعامل مع أكثر من كلاينت في نفس اللحظه :
وهذا هو كود السيرفر :
// MutliThread Server Using TCP|IP Socket
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class MultiThreadEchoServer
{
private static ServerSocket serverSocket;
private static final int PORT = 3000;
public static void main (String args[]) throws IOException
{
try
{
serverSocket = new ServerSocket(PORT);
}
catch (IOException e)
{
System.out.println("Unable To Attach Port");
System.exit(1);
}
while ( true )
{
Socket l = serverSocket.accept();
System.out.println("New Client Accpeted.........");
// send Socket to CleintHandling
ClientHandling clientHandling = new ClientHandling(l);
clientHandling.start();
}
}
}
class ClientHandling extends Thread
{
private Scanner input;
private PrintWriter output;
private Socket link;
public ClientHandling (Socket l)
{
link = l;
try
{
input = new Scanner(link.getInputStream());
output = new PrintWriter(link.getOutputStream(),true);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void run ()
{
String in , out;
do
{
in = input.nextLine();
out = "OK";
output.println(out);
}while ( ! in.equals("CLOSE") );
try
{
if ( link != null)
{
System.out.println("Closing Down Connection");
link.close();
}
}
catch (IOException e)
{
System.out.println("Cannot Disable");
}
}
}اما الكلاينت :
// Client Program for Port 3000import java.net.Socket;
import java.net.SocketException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.io.PrintWriter;
import java.io.IOException;
import java.util.Scanner;
public class TCPClient
{
private static Socket link;
private static final int PORT = 3000;
private static InetAddress address;
public static void main (String args[])
{
try
{
address = InetAddress.getLocalHost();
}
catch (UnknownHostException e)
{
System.out.println("Cannot find Host ID");
System.exit(1);
}
accessServer();
}
public static void accessServer ()
{
link = null;
try
{
link = new Socket(address,PORT);
Scanner input = new Scanner(link.getInputStream());
PrintWriter output = new PrintWriter(link.getOutputStream(),true);
String msgIn , msgOut;
Scanner usrInput = new Scanner(System.in);
do
{
System.out.print("Enter Message : " );
msgOut = usrInput.nextLine();
output.println(msgOut);
DayTime_Server_Client.rar
Port_Scanner.rar
Simple_Chat.rarhttp://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
بالنسبه الى JEditorPane وعندما نقوم باظهار محتويات موقع ، فاذا كان الموقع بسيط ولا يحتوي على جداول متداخله ، فراح يكون العرض شبه ممتاز ، أما اذا كان تصميم الموقع متقدم فراح يظهر الموقع بشكل رديئ ، والسبب أن هذه امكانيات JEditorPane متواضعه للغايه :) .
فمن أراد أن يكتب واحد مشابه فيمكن أن يقوم بالعمليه بشكل يدوي ويعمل parser للصفحه ، وهذا الأمر ليس بالبساطه المتوقعه ، فالـ Tag في html ليست لها standard واحد ، فمثلا يمكن أن يبدأ <h1> بدون end Tag ، وبعض المرات يكون فيه </h1> ، بالاضافه الى مثلا طريقه الكتابه هل هي captial أم Small ، اضافه عند اعطاء قيمه ما لtag ، فيمكن أن تكون هذه القيمه بين علامه تنصيص " " ، ويمكن أن تكتب تلقائي ..
لذلك الأمر ليس بالسهوله المتوقعه ... أما JEditorPane فكفايه أنه فهم وتعرف على أغلب الـ Tag ، ولكن بقي مظهر الصفحه رديئ قليلا ..
على العموم ، يمكن أن أنظر الى متصفحات مفتوحه المصدر بالجافا ، ونرى ما وصولوا اليه ، سواء باستخدام JEditorPane أو القيام بالأمر بشكل يدوي Parse HTML .
بالتوفيق .
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
ما شاء الله تبارك الله ... روعة اخي الكريم ... لقد عدت بي الى فترة عزيزة على قلبي ، حين انجزت مشروع تخرجي في برمجة الشبكات ... لا ادري ان اطلعت عليه ... لقد نشرته في المنتدى قبل اكثر من ثلاث سنوات على هذا الرابط ...
قرأت الموضوع و هو دسم لدرجة انك لا تريد ان تجاوز أي مقطع فيه :)
من الاشياء التي خطرت ببالي هو :
اقتباسلاحظ هنا أنه يحصل exception عندما نقوم بفتح بورت مفتوح مسبقا من قبل برنامج أخر وفي هذه الحاله سوف يحصل exception من نوع IOException
لماذا بذات IOException ؟ هل المسألة لانه نحن بنتعامل هنا من stream طالع عن طريق بورت معين؟
اقتباسكنت أريد أن أضع تمرين "دسم" أو يمكن ان نطلق عليه مشروع صغير ، ولكني سأجله قليلا ، حتى تستردوا أنفاسكم بعد هذه الجلسه الدسمه أيضا .
بانتظار التمرين :)
جزاك الله خير الجزاء
لا اله الا الله .. محمد رسول الله
(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)
يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين
فعلا رائع .... واعذرني اذا لم استطيع الابحار به كثيرا لسبب الدراسة
ولكنني لن استغني عن حدودك المائية ولن يطول بعدي...
اخوكم شادو صاحب اللوك الجديد :D
أحب أن أهنئكم على ملاحظاتكم الدقيقه ، والتي تدل على حسن المتابعه ، بارك الله فيكم أخوتي .
بالنسبه للداله البناء :
public ServerSocket(int port) throws IOException
فهي في الحقيقه تولد Exception أخر وهو BindException ، ولكن أنا أختصرت الطريق وقلت أتعامل مع IOException لأنه الكلاس الأب له ، المهم هو أنBindException يحصل عندما تكون هناك مشكله في انشاء السوكت بالبورت المحدد فقط (مثلا البورت مستخدم من قبل سيرفر ثاني ) ، أما IOException فهو يحدث في حال أردت فتح منفذ من 1 الى 1023 ولم تكن لديك صلاحيات لهذه العمليه ، وهي تحدث في أنظمه Unix-Like مثل linux , Mac OS X عندما تكون دخلت للنظام بحساب غير root وأردت فتح البورت بهذا الحساب .
أي شكل داله البناء تكون هكذا :
public ServerSocket(int port) throws BindException, IOException
شاكر لك سؤالك الجيد مره أخرى ...
بالنسبه الى :
if ( Socket != null ) socket.close();
فعلا ، خطأ مطبعي قاتل :) ... ويجب أن نغلق الكائن وليس الكلاس . لذلك نغير من S الى s في جمله الـ if .
شكرا على التنبيه أختي الكريمه ..
بالنسبه لمشروعك أختي بنت اليمن ، فماشاء الله عليه ، مشروع ممتاز وفكرته جيده ، لم أطلع على الموضوع بالكامل فقط مريت عليه بشكل سريع جدا ، لا زلت في مرحله الأطلاع ، وقد أعجبني شرح TCP|IP ، على العموم اللى فهمته ، أننا مثلا أذا أردنا أن نتحكم ببورت معين في الكلاينت مثلا 1000 ، نقوم بارسال هذا البورت للكلاينت ، وأمنع الكلاينت من عمل socket مثلا باستخدام البورت 1000 (يعني المنع من الكلاينت ) . هل هذا صحيح ....
وما هي أمكانيه تطبيق المشروع بجافا في رأيك ؟
نكمل الأن في ما كنت قد أقترحته وهو برنامج مبسط لمراقبه الجهاز الأخر ، عن طريق أخذ ScreenShot منه ..
والسؤال هو كيف يمكن أيجاد Screen Shot ؟
وقد كنت أعتقد أن الأمر سيكون معقد لعدم توفر داله بهذا الأمر في جافا ، ولكن لحسن حظنا طلعت هناك داله تقوم بهذا الأمر ، لذلك وفرت علينا هذه الداله الكثير من الخطوات التي كنا سنفعلها في حال لم نجد داله لهذا الأمر (ويحتمل بعد ذلك أن تعمل أو لا تعمل :) ) .
الحل عن طريق الداله :
public BufferedImage createScreenCapture(Rectangle screenRect)
الموجوده في الكلاس java.awt.Robot .
لاحظ أن الداله تستقبل كائن من نوع Rectangle (وبه نحدد الطول والعرض الذي نريده في الصوره ) وترجع كائن من نوع BufferedImage ، وباستخدام كائن أخر مثلا ImageIO نستطيع كتابه هذا الكائن في ملف مباشره .
في الكود التالي ، حصلنا على أبعاد الشاشه كامله ، ومررناها للcreateScreenCapture ، ومن ثم حصلنا على الصوره في الكائن screencapture .
// capture the whole screen BufferedImage screencapture = new Robot().createScreenCapture( new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
الأن نقوم بفتح ملف ونكتب فيه هذه الصوره (هذا في حال أردت حفظ الصوره في الجهاز ) :
// Save as JPEG
File file = new File("screencapture.jpg");
ImageIO.write(screencapture, "jpg", file);
// Save as PNG
// File file = new File("screencapture.png");
// ImageIO.write(screencapture, "png", file);ملاحظه ، أبعاد الشاشه التي حصلنا عليها سابقا ، كانت على حجم الشاشه كامله ، فاذا أردنا بعد معين ، يمكن أن نحدد القيم في داله البناء لـ Rectangle ، مثلا هنا سوف نبدأ من النقطه 15*15 ونذهب 150 في الطول والعرض .
BufferedImage screencapture = new Robot().createScreenCapture( new Rectangle( 15, 15, 150, 150));
وفي حال أردنا أن نحصل على شاشه البرنامج فقط Frame ، يمكن أن نستخدم :
BufferedImage image = new Robot().createScreenCapture( new Rectangle( myframe.getX(), myframe.getY(), myframe.getWidth(), myframe.getHeight() ) );
وهذا مثال بسيط :
// Get ScreenShot
// Romansy
import java.awt.Toolkit;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.FlowLayout;
import java.awt.AWTException;
import java.awt.image.BufferedImage;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.imageio.ImageIO;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileNotFoundException;
public class Demo
{
public static void main (String args[])
{
ScreenShot app = new ScreenShot();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.setVisible(true);
}
}
class ScreenShot extends JFrame
{
private JButton getScreenButton;
public ScreenShot ()
{
setTitle("Get ScreenShot Application");
Toolkit kit = Toolkit.getDefaultToolkit();
Dimension size = kit.getScreenSize();
final int width = size.width ;
final int height = size.height;
setSize(width/2 , height/2);
setLocation(width/4 , height/4);
getScreenButton = new JButton("Get Screen Shot");
getScreenButton.addActionListener(
new ActionListener()
{
public void actionPerformed (ActionEvent event)
{
try
{
Rectangle rectangle = new Rectangle(0,0,width,height);
// to get Screen Shot of this program only , delete the comment from this line
//Rectangle rectangle = new Rectangle(getX(),getY(),
// getWidth(),getHeight());
Robot robot = new Robot();
BufferedImage img = robot.createScreenCapture(rectangle);
FileOutputStream file = new FileOutputStream("screenShot.jpg");
ImageIO.write(img,"jpg",file);
file.close();
}
catch ( AWTException e)
{ e.printStackTrace(); }
catch ( FileNotFoundException e)
{ e.printStackTrace(); }
catch ( IOException e)
{ e.printStackTrace(); }
}
}
);
setLayout ( new FlowLayout() );
add(getScreenButton);
}
}الان بعد تنفيذ البرنامج والضغط على الصوره ، تم حفظ صوره أسمها screenShot1.jpg في نفس مسار البرنامج الحالي .

الأن يمكنك أن تقوم ببعض التعديلات على البرنامج ، وتعمل الـ Client/Server بحيث كل ما يطلب العميل الصوره ، يقوم الخادم بارسالها اليه .. وتبقى المشكله أننا ستكون لدينا الصوره في السيرفر والتي نوعها BufferedImage ، ونريد أن نرسلها للكلاينت ، ولن تستطيع ارسالها كـ Object باستخدام writeObject لأن هذه الداله لا تكتب الا الكائنات التي تكون معلمه بـ Serializable ، والصوره BufferedImage غير Imeplements Serialzable interface .
أسهل حل ، وأسوأ حل هو أن تقوم بحفظ الصوره في الملف في السيرفر ، وتقوم بغلقه ومن ثم تفتح الملف مره أخرى وتقرأه عادي ومن ثم أرسال متحوياته (ضعها في مصفوفه بايت) كـ Object . (كما في المثال الخاص بارسال صوره أو فيديو في الجلسه السابقه بالضبط ) .
حلول أخرى وهي في الدوال الموجوده في الكلاس javax.imageio.ImageIO :
static BufferedImage read(ImageInputStream stream) static BufferedImage read(InputStream input) static boolean write(RenderedImage im, String formatName, ImageOutputStream output) static boolean write(RenderedImage im, String formatName, OutputStream output)
على العموم أنا بصدد حلها بهذه الطريقه الأن ... ويمكنكم البحث أيضا إن أردتم .
نعود التمرين الذي وعدتكم به ، من النوع السهل اذا كنت متقن جيد للجافا ، والا فسوف يكون من النوع المتوسط أو الصعب جدا :) .
أكتب برنامج محاكي لخدمه FTP Client/Server . فقط محاكي له بشكل مبسط ، ولا نريد واجهه GUI في بدايه الأمر للتبسيط ، ومن يستطيع عمل واجهه فلا بأس .
المهم السيرفر يفهم 5 أوامر هي :
DIR
GET
PUT
HELP
QUIT
وطبعا يقوم باستقبال هذه الأوامر من الكلاينت ، وفي حال أستقبل أمر أخر غير هذه الأوامر الخمسه يقوم بالرد عليه بأن الأمر غير معروف لديه .
ولتصعيب الأمر قليلا ، هناك معاملات طبعا ترسل لهذه الأوامر هي :
في DIR (وهي تستخدم لعرض مجلدات مسار معين) :
في حال أرسل المتسخدم : DIR
(فقط من غير مسار) يتم عرض جميع المحتويات في المسار الحالي للسيرفر (طبعا يتم ارسالها للكلاينت ويتم عرضها لدى الكلاينت) .
في حال أرسل المتسخدم : DIR C:\\a
نقوم عرض جميع محتويات المجلد a ( طبعا أسماء المحتويات فقط ) .
في GET يجب أن أحدد ما الذي أريد تحميله من السيرفر Download From Server .
يعني بهذا الشكل : GET C:\\Wajdy\romansy.jpg
وهنا يقوم السيرفر بارسال الصوره للكلاينت ، ويقوم الكلاينت بحفظها لديه في المسار الحالي للبرنامج ، وبنفس اسم الصوره .
في PUT يجب أن أحدد ما الذي أريد تحميله ألى السيرفر Upload to Server .
يعني بهذا الشكل : PUT C:\\Wajdy\romansy.mp3
وهنا يقوم الكلاينت بارسال الملف الى السيرفر ، ويقوم السيرفر بحفظها لديه في المسار الحالي للبرنامج ، وبنفس اسم الملف.
هذا في حاله كانت GET و PUT لملف معين ، في حال كانت لمجلد ما ، فنقوم بارسال|تحميل محتويات الدليل الحالي فقط (من غير الدخول الى الـ Subdirectory ) . ونقوم بحفظها في الجهه الأخرى بنفس أسم المجلد ، والمحتويات أيضا بنفس الأسم .
HELP لا توجد بها معاملات ، ونقوم هنا بارسال شرح مبسط للأوامر التي يتعامل معها السيرفر .
QUIT لكي أفصل الكلاينت ، وسأساعدكم هنا : قوموا بغلق السوكت الخاص بالكلاينت :) :) . ولا تنسوا أرسال رساله وداع له ، اضافه الى مثلا وقت تعامله مع السيرفر مثلا : 10 دقايق ، أو ساعه وهكذا .
أيضا عندما يتصل الكلاينت بالسيرفر ، مباشره يقوم السيرفر ، بارسال رساله ترحيبه له ، ويعرض له مثلا التاريخ والوقت الحالي في السيرفر ، بعدها يكون السيرفر في حال انتظار للأستقبال الأوامر من الكلاينت ، وفي حال أرسل الكلاينت الأمر الأول ، وقام السيرفر بالرد ، يقوم الكلاينت مره أخرى بادخال أمر أخر ، والسيرفر يستقبل أيضا ... أي أن العمليه لا تنتهي الا بكتابه QUIT فقط ..
نريد هذا السيرفر يتعامل مع أكثر من كلاينت في نفس اللحظه .
نكتفي بهذا القدر من المتطلبات ...
وقبل أن ننتهي الأن ، أحب أن أعرض بعض الأمثله التطبيقيه على الدرس ، فقط سأعطيكم الأفكار وعليكم التطبيق :) :) .
البرنامج الأول :
Secure Client/Server With ROT13
وهنا شات عادي بين الكلاينت والسيرفر ، لكن قبل أرسال أي جمله ، نقوم بتشفيرها ، وذلك بزياده 13 على كل حرف من الحروف ، وعندما نستقبلها من الجهه الأخرى نقوم بطرح 13 منها وسوف عرضها هناك .
يمكن تطوير البرنامج واستخدام Modern Cipher مثل DES , 3DES ,AES , RSA ، والشيء الجيد في جافا أن هناك مكتبه خاصه للتعامل مع هذه الخورازميات ، ويمكنك التشفير فقط بعمل كائن من الكلاس فقط ، والمكتبه تحتوي أيضا على خوارزميات تواقيع رقميه وبعض الأمور الأخرى .
البرنامج الثاني :
Chat Room With Private Room
هنا نقوم بكتابه شات ، بين أكثر من مستخدم ، طبعا لأننا لم ندرس Multicast Socket الى الأن ، فيمكن تطبيق الفكره بشكل مبسط ، وذلك بحفظ سوكت أي كلاينت يتصل بالسيرفر مثلا في مصفوفه أو ArrayList ، المهم عندما يرسل الكلاينت رساله للسيرفر ، يقوم السيرفر باستقبال هذه الرساله ، ويقوم بارسال هذه الرساله الى جميع الكلاينت المجودين في المصفوفه . كنت قد كتبت واحد مثله فيما مضى ، ولكن تبدأ المشاكل في حال خرج كلاينت ما ، يجب أن تحذف السوكت الخاص به من المصفوفه وهنا يجب أن تحاول حل هذه المشكله بأي طريقه كانت :) ، يمكنك أيضا أن تزود كل عميل أراد أن يدخل JOptionPane.showInputDialog يقوم بادخال اسمه هنا ، وعندما يبدأ الشات ، نقوم بعرض جميع أسماء المتسخدمين الموجودين حاليا . يمكن تحسين الفكره أيضا وجعل المستخدم يدخل اسمه ويختار صوره أيضا ، وهكذا دواليك .. أما الPrivate Room فلم أقم بكتابه تطبيق يدعم هذه الميزه ، لذلك قم بتطبيقها أن أردت وأعرض علينا برنامجك ..
البرنامج الثالث :
Pizza Ordering System
وهنا نريد عمل برنامج لللطلبات في مطعم بيتزا ، ويقوم الكلاينت من منزله باختيار البيتزا (وأي مأكولات أخرى ، لكن للتبسيط فقط نحصرها في البيتزا فقط ) ، ويقوم بتعبئه معلومات ويرسل الطلب ، ويرد عليه السيرفر بالسعر $ ، وبرساله شكر أيضا :) .
يمكن أن تكون صوره العميل بهذا الشكل :

ويمكن أن نضيف أشياء أخرى ، كصوره لكل نوع ويقوم المتسخدم باختيار ما يريد ، وأظهار سعر كل نوع ، وأي خيار أخر ...
السيرفر يكمن أن يكون على console لو أردت ، أو يمكن تطوير واجهه متقدمه للمطعم . لا توجد مشكله في هذا ..
يمكن تطوير الفكره ، وجعلها تعمل على الأنترنت ، بدلا من أن نكون محصورين في شبكه صغيره محليه هو أرخص بالتأكيد . لكن سوف تستخدم مثلا Java Applet مع JSP في الكلاينت ، وتستخدم Servlet في السيرفر .. (ليست لدى معرفه بهذا النوع ).
وللحديث بقيه ان شاء الله ... :wub:
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
الف شكر اخ رومانسي على الشرح الوافي و الكافي ......
و انا من المتابعين لك في دروسك الرائعة و المبسطة , و استفدت منها الكثير
بالمناسبة برنامج FTB انتهيت من حلة من اسبوع ( و إن شاء الله سوف اضع حله في اقرب فرصة )
بس التطبيقات الأخرى فيها أفكار جيدة و نبد بالحل أنشالله ..............
THANX MR:ROMANCY
FOOOOOOOOX

لا اله الا الله .. محمد رسول الله
(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)
يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين
بسم الله الرحمن الرحيم
بالنسبة لسؤال الأخت dr_sara في الفرق بين sockets و ال rmi :
ال socket هو low-level network programming أما rmi فهو high-level حيث انه يعتمد علي ال sockets
ال sockets عباره عن server يفتح connection ل client يستغل هذه ال connection كما أوضح الأخ الفاضل .
ال rmi هو عبارة عن object serialization في ال network sockets ( كما نعلم ان ال serialization هو عملية تثبيت او حفظ للobject في وسط غير الزاكره العشوائية للإستخدام فيما بعد) و كما نعلم ان ال serialization قد تتم علي القرص الصلب أو تتم علي network socket و في حالة ال rmi تتم كتابة ال object ل network socket تماما كما تتم كتابتة علي القرص الصلب - و لذا يلاحظ ان ال objects التي تستخدم في ال rmi يجب ان تكون serialiazable .
و تسمى عملية كتابة ال objects في ال network sockets ب Object Streamming .
الخلاصة :
من هنا نجد أن ال network sockect هو low-level network programming .
أما ال rmi فهو تقنية أكثر تعقيدا في الاستخدام لكنه يقوم بعمل اشياء كثير جدا بالنيابة عنا و هو حال التقنيات الاكثر تطور يكون استخدامها أصعب لكنها تخفي تفاصيل برمجية ممله .
لمزيد من التفاصيل حول ال RMI :
حياك الله أخي رومنسي ... للأمانة اعتقد أني احتاج إلى يومين آخرين لتغطية و فهم الموضوع بشكل جيد و حتى أضع برامجي (بدأت اجرب افكار عديدة مما اخذ مني وقت) ... فهل من الممكن أن يتوقف الموضوع حتى يوم الاحد ؟؟ (اشعر بالخجل من هذا الطلب) :rolleyes:
لدي أسئلة و استفسارات عديدة و لا أريد أن يتراكم الموضوع عليّ ... ... جزاك الله عنا خير الجزاء
لا اله الا الله .. محمد رسول الله
(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)
يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين
بارك الله فيك أخي romansy , على موضوعك الرائع .
وحقيقة انا عندي خلفية لابأس بها عن Sockets و RMI و بعض CORBA و فد انشأتن مشروع تخرجي بالاعتماد على RMI.
لكن عندي سؤال :::
لقد شاهدت يوما برنامج جميل يدعى NetOP يستخدم في التحكم في شبكات Peer - Peer , وهذا البرنامج به العديد من التقنيات الجميلة و التي استطهت تطبيق بعضها بشكل مبسط , با ستخدام Java مثل ارسال ملفات او صور او حتى Chat .. الخ
ولكن هناك شيء لم استطع عملها ربما لقلة خبرتي أو لعدم توفر ادوات في الجافا تدعم هذا الشيء , و هو كيفية نقل شاشة الحاسوب للجهاز المزود ببرنامج NetOP إلى باقي اجزاء الشبكة , حيث ان باقي المستخدمين على الشبكة يستطيعون رؤية شاشة الجهاز الرئيسي من اماكنهم , ويشاهدو ايضا مايحدث فيها من تغيرات و تحريك للماوس أو فتح برامج ... الخ.
فهل يا أخي هناك شيء يدعم هذا في الجافا و أنا اظن ذلك , وإذا كان كذلك و لديك خبرة في هذا المجال فياريت تعطينا جزء من خبرتك؟؟؟!!!!!!!!!!.
MKSoft كتب:ولكن هناك شيء لم استطع عملها ربما لقلة خبرتي أو لعدم توفر ادوات في الجافا تدعم هذا الشيء , و هو كيفية نقل شاشة الحاسوب للجهاز المزود ببرنامج NetOP إلى باقي اجزاء الشبكة , حيث ان باقي المستخدمين على الشبكة يستطيعون رؤية شاشة الجهاز الرئيسي من اماكنهم , ويشاهدو ايضا مايحدث فيها من تغيرات و تحريك للماوس أو فتح برامج ... الخ.فهل يا أخي هناك شيء يدعم هذا في الجافا و أنا اظن ذلك , وإذا كان كذلك و لديك خبرة في هذا المجال فياريت تعطينا جزء من خبرتك؟؟؟!!!!!!!!!!.
قام مجموعة من زملائي بالكلية بهذا العمل (Remote Desktop) بإستخدام ال sockets و بعض الدوال في java.io .
ياريت اخي مبتدأ جافا إذا عندك اي مساعدة من اصدقاءك او غيرهم انك تحاول تفيدنا فيها و بارك الله فيك و في الإخوة
السلام عليكم ... حياكم الله جميعاً ...
و حياك اخي رومنسي ... انتهيت من قراءة و تطبيق الدروس ... و انا مستعدة الآن لأي إضافة هنا ...
جزاك الله كل الخير .. لا تدري مدى استفادتي من هذه الدروس .. و مدى الافكار التي تمر عليّ بسببها ...
فقط يتبقى لي استفسار بسيط و لا ادري إن تم ذكره و هو لماذا نستخدم true عند فتح تدفق stream كما يلي :
PrintWriter output = new PrintWriter(socket.getOutputStream(),true);
الشيء الاخر .. هل مر عليك شيء له علاقة بعمل فيديو استريم بين الشبكة ... يعني هل ممكن اعمل عرض فيديو في جهاز ثم يبث اول بأول عبر الشبكة (Live stream) ... (لا تشغل بالك إن لم يمر عليك الموضوع )
و ايضاً الف شكر على طريقة الـ Screen Shot و التي لم اتوقع أن تكون بهذه البساطة ... :)
بالنسبة لمشروعي .. فالفكرة هي التحكم بمنافذ الـ clients عن بعد و ذلك بإرسال ارقام المنافذ المراد إغلاقها الى الـ clients .... السر في اغلاق المنافذ هو تتبع جدول الـ TCP في العميل و الذي يحوي معلومات و حالة أي اتصال يتم إنشاءه ... بحيث اذا تم إنشاء اتصال عبر أي منفذ تم وضعه كمنفذ محضور يتم تغير وضع الاتصال في جدول الـ TCP الى closed ...
اعتمد المشروع على دوال الـ API و بالتالي فهو قابل للتطبيق في أي لغة ... الفيجول بيسك كان من اجل الحصول على قائمة الاجهزة المتصلة حالياً و لإنشاء الواجهات و بالطبع للتعامل مع قاعدة البيانات ...
اخيراً بالنسبة لواجب الـ FTP فلا اعتقد اني استطيع إنجازة حالياً بالشكل المطلوب ... لقد قمت بعمل الامر DIR منفصلاً .... و اتصور ان اجابة dr_sara العزيزه كافية (جزاها الله خيراً)
عموماً ... ما زلت متابعة معكم الموضوع ... لانه و رغم الانشغال ، الموضوع فعلاً يدفقك للتتابعة :)
سلامي للجميع ...
لا اله الا الله .. محمد رسول الله
(* ربِ اجعلني مقيم الصلاة و من ذريتي ، ربنا و تقبل دعـاء *)
يا حيّ يا قيـوم ... برحمتك استغيث ... اصلح لي شأني كله و لا تكلني الى نفسي طرفة عين
اقتباساخى الفاضل كاتب الموضوع كنت حابة اسال بما اننا نكتب برنامجيين واحد للclient والثانى server هل كل منهم ممكن ان يكتب بلغة مختلفةبحث يكون اللغتين لا يعتمدوا على os
مش عارفة هل تفكيرى صحيح ام خاطىء مئة بالمئة
في اعتقادي أختي الكريمة أنه لا يوجز ذلك بالطريقة التقليدية و هي استخدام Socket , و إنما يجوز ذلك باستخدام تقنية اسمها CORBA , حيث يمكن استخدام لغات مختلفة في تطوير النظام . هذا و الله أعلا و أعلم.
لكاتب الموضوع
بارك الله فيك أخي romansy , على موضوعك الرائع .
وحقيقة انا عندي خلفية لابأس بها عن Sockets و RMI و بعض CORBA و فد انشأتن مشروع تخرجي بالاعتماد على RMI.
لكن عندي سؤال :::
لقد شاهدت يوما برنامج جميل يدعى NetOP يستخدم في التحكم في شبكات Peer - Peer , وهذا البرنامج به العديد من التقنيات الجميلة و التي استطهت تطبيق بعضها بشكل مبسط , با ستخدام Java مثل ارسال ملفات او صور او حتى Chat .. الخ
ولكن هناك شيء لم استطع عملها ربما لقلة خبرتي أو لعدم توفر ادوات في الجافا تدعم هذا الشيء , و هو كيفية نقل شاشة الحاسوب للجهاز المزود ببرنامج NetOP إلى باقي اجزاء الشبكة , حيث ان باقي المستخدمين على الشبكة يستطيعون رؤية شاشة الجهاز الرئيسي من اماكنهم , ويشاهدو ايضا مايحدث فيها من تغيرات و تحريك للماوس أو فتح برامج ... الخ.
فهل يا أخي هناك شيء يدعم هذا في الجافا و أنا اظن ذلك , وإذا كان كذلك و لديك خبرة في هذا المجال فياريت تعطينا جزء من خبرتك؟؟؟!!!!!!!!!!.
تم تعديل هذه المشاركة بواسطة MKSoft في 1 أبريل 2008 في 18:33