الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

نقل الملفات عبر Tcp Socket كيف انقل الملف وبنفس الوقت اتبادل الرسائل مع السيرفر

بدأه Kmarwani في 25 يناير 2010 · 4 رد · 1,786 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

مرحبا

احاول نقل ملف من والي client - server

بمعنى برنامج بسيط يقوم بـ download و upload

قدرت اسوي تنزيل للملف بدون مشاكل واظن رفع الملف للسيرفر ماراح تواجهني مشكله كبري

مشكلتي الاساسيه في انني احتاج الى ان اتواصل مع السيرفر عبر الرسائل .. مثلا ارسل له رساله اقول له "احتاج تنزيل الملف الفلاني ارسله لي" او مثلا "سوف ارسل لك ملف جهز نفسك"

من الخارج قد يبدو للبعض انه لاتوجد مشكله

لكن بعد كتابة الكود اتضح لي انه لايوجد الا قناه واحده للتواصل وهنا تظهر المشكله بالنسبه لي

هل استخدمها في تبادل الرسائل مع السيرفر او استخدمها لنقل البيانات "الملف بذاته"

توضيح اكثر

فرض ارسلت للسيرفر رساله تحتوي على "upload" وينفس الوقت ارغب في ارسال الملف نفسه الى السيرفر فكيف افصل هذه الرساله عن الملف بذاته بحيث السيرفر يعرف انه هذي رساله او هذي بيانات ملف

الكود حفي فيه مشاكل اخرى وطويل وممكن يتعب بقراءته لذلك لا اعتقد ان من المجدي نشره هنا

لكن في كود مشهور وبسيط يوضح الفكره ومككن يستفاد منه هنا

في هذا الكود فقط تنزل الملف لكن بدون تبادل رسائل بين server و الـ client

server

import java.net.*;
import java.io.*;

public class FileServer {
  public static void main (String [] args ) throws IOException {
    // create socket
    ServerSocket servsock = new ServerSocket(13267);
    while (true) {
      System.out.println("Waiting...");

      Socket sock = servsock.accept();
      System.out.println("Accepted connection : " + sock);

      // sendfile
      File myFile = new File ("source.pdf");
      byte [] mybytearray  = new byte [(int)myFile.length()];
      FileInputStream fis = new FileInputStream(myFile);
      BufferedInputStream bis = new BufferedInputStream(fis);
      bis.read(mybytearray,0,mybytearray.length);
      OutputStream os = sock.getOutputStream();
      System.out.println("Sending...");
      os.write(mybytearray,0,mybytearray.length);
      os.flush();
      sock.close();
      }
    }
}

client

import java.net.*;
import java.io.*;

public class FileClient{
  public static void main (String [] args ) throws IOException {
    int filesize=6022386; // filesize temporary hardcoded

    long start = System.currentTimeMillis();
    int bytesRead;
    int current = 0;
    // localhost for testing
    Socket sock = new Socket("127.0.0.1",13267);
    System.out.println("Connecting...");

    // receive file
    byte [] mybytearray  = new byte [filesize];
    InputStream is = sock.getInputStream();
    FileOutputStream fos = new FileOutputStream("source-copy.pdf");
    BufferedOutputStream bos = new BufferedOutputStream(fos);
    bytesRead = is.read(mybytearray,0,mybytearray.length);
    current = bytesRead;


    do {
       bytesRead =
          is.read(mybytearray, current, (mybytearray.length-current));
       if(bytesRead >= 0) current += bytesRead;
    } while(bytesRead > -1);

    bos.write(mybytearray, 0 , current);
    bos.flush();
    long end = System.currentTimeMillis();
    System.out.println(end-start);
    bos.close();
    sock.close();
  }
}

اي مساعده او نصيحه او تفكير بصوت عالي راح تساعدني

تحيتي

#2

اضافة

مضطر استخدم port واحد

لأنني سوف اطلب من المستخدم ادخال رقم الـ port وعنوان السيرفر ( لذلك لااستطيع ان اخدع المستخدم واضيف Port مخفي آخر )

لأنه لو من الممكن استخدام اكثر من port كان ببساطه خصصة واحد للرسائل والاخر لنقل الملف نفسه

تحيتي

#3

استخدم أخي إشارة رمزية قبل الإرسال :

مثلا : ارسل حرف T متبوعا بالنص ( على شكل سلسلة من Bits ) المراد إرساله للسيرفر للدلالة علة أنه نص. و أرسل حرف F متبوعا بالملف المرسل للدلالة على إرسال ملف .

#4

مثلما قال لك محمد عشان تميز بين النص والملف لازم تعطيه إشارة عشان يفرق بين النص والملف وافصل بين الإشارة والبيانات المراد إرسالها بأي رمز مثلاً @ أو # بعد كذا تسويله split("#") عند المستلم وتاخذ أول عنصر وتقارنه إذا كان T تعامل معه كنص وإلا فهو ملف.

أو تقدر ترسل له أمر بفتح منفذ جديد مؤقت متعارف عليه بين الكلاينت والسيرفر خاص بنقل الملفات دون علم المستخدم يقوم بغلقة بمجرد الإنتهاء من إرسال الملف.

سبحان الله أنا عندي عكس مشكلك تماماً , قبل فترة سويت برنامج يستعرض الملفات عن بعد ومشى حلاوه , لكن عندما اضفتله امكانية تحميل ورفع الملفات سوى مشكله , أحياناً يرسل وأحياناً لا دون ان يعطيك أي رسائل خطأ

هذا هو Client.java

Server.java


HeartOutputStream myHeart;
OutputStream myHeartOutStream;

myHeartOutStream = MAllaw.getHeart().getOutputStream();
myHeart = new HeartOutputStream(myHeartOutStream);

while(myHeart.isStillBeating())
myHeart.write("I ♥ Java");

#5

عليك بعمل حوار مفهوم للطرفين (simple protocol) ، كما ذكر الشباب يمكن ان ترسل اشاره # ثم ارسل الملف ، من جهه السيرفر يجب أن يكون لديك thread لاستقبال الرسائل ، داخل الحلقة loop في هذا الthread قم بقرائه القادم من العميل وقم بعمل فحص له، فاذا كانت معناهاا # فهذا يعني انك أيضا ستستقبل مدخل اخر وهو الملف ،، وهكذا ..

في حال كبر البرنامج سوف تصبح هذه الاشارات مزعجه للغايه ولن تستطيع صيانه البرنامج بسهوله ، لذلك قم بعمل كلاس صغير لهذا الغرض :

public class Message {
    public static final String REGISTER = "1" ;     // when client register
    public static final String ERR_REGISTER = "2" ; // server response , error
    public static final String SUC_REGISTER = "3" ; // server response , ok

    public static final String LOGGIN = "4" ;       // when client loggin
    public static final String ALREADY_LOGGIN = "144"; // when user log again
    public static final String ERR_LOGGIN = "5";    // server response , error
    public static final String SUC_LOGGIN = "6";    // server response , ok
}

مثلا العميل يريد تسجيل الدخول فيرسل LOGGIN للسيرفر ، والسيرفر سوف يريد عليه ايضا بالرفض ERR_LOGGIN او القبول SUC_LOGGIN ..وهكذا ،،

بالتوفيق،

http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة

https://moalfat.com  للكتب الالكترونية والكورسات التعليمية

Everything we see now is just an engineering solution based on old science

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…