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

مشكلة في إستقبال صورة من السيرفر بإستخدم Sockets

بدأه MKSoft في 24 فبراير 2010 · 8 رد · 1,232 مشاهدة · في برمجة الشبكات والتطبيقات الموزعة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم إخواني ..

قمت بتصميم برنامج بسيطة يستخدم Socket , بحيث يقوم الخادم بتقديم خدمة ارسال ملف إلى Client , وجاء التصميم على النحو التالي :

FileServiceServer : السيرفر الذي يقدم خدمة إرسال الملفات إلى الزبائن .

MasterServer : وهو السيرفر الوسيط بين الزبائن و بين خدمة الملفات FileServiceServer .

Client : الذي يطلب الخدمة .

كما تشاهدون في الصورة .. الية النقل و الإستقبال و الإرسال.

Network.jpg

في البرنامج الذي صممته قمت باختباره على النحو التالي :

يقوم الزبون بطلب الخدمة من MasterServer و ذلك بإرسال الإشارة f- , ويليها إرسال الزبون أيضا مسار الملف المطلوب من السيرفر ..

يقوم الوسيط السابق بإرسال مسار الملف إلى File Service Server حتى ينفذ الخدمة المطلوبة و يرسل الملف المطلوب إلى الزبون ( مارا بــ الوسيط Master Server ) ,و يقوم البرنامج بحفظه على جهاز الزبون تحت المسار و اسم الملف التالي :

C:\\myImg.jpg

هنا على افتراض ان الملف المطلوب من السيرفر هو عبارة عن صورة .

هنا ظهر مشكلتين :

الأولى : أن السيرفر يرسل الصورة إلى الزبون ,, لكن للأسف تكون مشوهة ...

الثانية : أنه لو حاول الزبون طلب الخدمة ثانية من خلال إرسال الإشارة f- و مسار الصورة , فإنه يحدث Exception .

اسف على الإطالة , وأرجو منكم الفائدة و جزاكم ربي خيرا .

الكود : كما يلي :

FileService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;

namespace FileServiceServer
{
    class FileService
    {
        private TcpListener tcp;
        private BinaryReader reader;
        private BinaryWriter writer;
        private NetworkStream netStream;
        private Socket socket;

        public void connect()
        {
            tcp = new TcpListener(6500);
            tcp.Start();
            Console.WriteLine("FileService start..");
            socket = tcp.AcceptSocket();
            Console.WriteLine("FileService accept Master Server..");
            netStream = new NetworkStream(socket);
            reader = new BinaryReader(netStream);
            writer = new BinaryWriter(netStream);

            serveClient();
        }
        public void serveClient()
        {
            while (true){
                String filePath = reader.ReadString();
                byte[] buf = File.ReadAllBytes(filePath);

                int size = buf.Length;
                writer.Write(size);
                writer.Write(buf);}
        }
        public void close()
        {
            writer.Close();
            reader.Close();
            socket.Close();
            tcp.Stop();
        }}}

MainServer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Threading;

namespace MasterServer
{
    class MainServer
    {
        private TcpListener tcp;

        private TcpClient fileServiceClient;
        private TcpClient calcServiceClient;

        private NetworkStream fileServiceStream;
        private NetworkStream calcServiceStream;

        private BinaryWriter fileServiceWriter;
        private BinaryWriter calcServiceWriter;

        private BinaryReader fileServiceReader;
        private BinaryReader calcServiceReader;

        public void connect()
        {
            connectToMainServers();
            beMainServerForClient();
        }
        public void connectToMainServers()
        {
            fileServiceClient = new TcpClient("localhost", 6500);
            fileServiceStream = fileServiceClient.GetStream();

            fileServiceWriter = new BinaryWriter(fileServiceStream);
            fileServiceReader = new BinaryReader(fileServiceStream);
        }
        public void beMainServerForClient()
        {
            tcp = new TcpListener(12500);
            tcp.Start();
            Console.WriteLine("Master Server start..");
            ThreadStart t = new ThreadStart(recive);
            Thread thread = new Thread(t);
            thread.Start();
        }
        public void recive()
        {
            Socket socket = tcp.AcceptSocket();
            Console.WriteLine("Master Server accept new Client..");
            NetworkStream stream = new NetworkStream(socket);

            BinaryReader reader = new BinaryReader(stream);
            BinaryWriter writer = new BinaryWriter(stream);
            while (true)
            {
                String mark = reader.ReadString();
                Console.WriteLine("Master Server Check for Choice: "+mark);
                if (mark.Equals("-f", StringComparison.CurrentCultureIgnoreCase))
                {
                    String path = reader.ReadString();
                    Console.WriteLine("Master Server recive Path := "+path);
                    fileServiceWriter.Write(path);

                    int size = fileServiceReader.ReadInt32();

                    byte[] buf = new byte[size];

                    fileServiceReader.Read(buf, 0, buf.Length);
                    writer.Write(buf.Length);
                    writer.Write(buf, 0, buf.Length);
                    Console.WriteLine("Master Server send the File..");
                }
                else
                {
                    writer.Write("Server >> Thanks for sending anything..");
                }
            }
        }
    }
}

Client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;

namespace ClientsDomain
{
    class Program
    {
        static void Main(string[] args)
        {
            TcpClient client = new TcpClient("localhost", 12500);
            NetworkStream net = client.GetStream();
            BinaryReader reader = new BinaryReader(net);
            BinaryWriter writer = new BinaryWriter(net);

            Console.Write("Client >> ");
            String mark = Console.ReadLine();
            while (!mark.Equals("exit", StringComparison.CurrentCultureIgnoreCase))
            {
                if (mark.Equals("-f", StringComparison.CurrentCultureIgnoreCase))
                {
                    writer.Write(mark);
                    writer.Flush();
                    Console.Write("Client >> Enter Path : >> ");
                    String path = Console.ReadLine();

                    writer.Write(path);
                    int size = /*int.Parse(*/reader.ReadInt32()/*)*/;
                    byte[] buf = new byte[size];

                    reader.Read(buf, 0, buf.Length);

                    File.WriteAllBytes("C:\\myImg.jpg", buf);

                }
                Console.Write("Client >> ");
                mark = Console.ReadLine();
            }
        }
    }
}
1
#2

وعليك السلام اخي الكريم

اقتباس
الأولى : أن السيرفر يرسل الصورة إلى الزبون ,, لكن للأسف تكون مشوهة ...

في العادة سبب ذلك يكون عدم ارسال أو استقبال كامل الـ Bytes لملف الصورة وفي العادة يكون السبب في طريقة تحديد Size الـ Buffer عند الإرسال أو الإستقبال ...

اقتباس
الثانية : أنه لو حاول الزبون طلب الخدمة ثانية من خلال إرسال الإشارة f- و مسار الصورة , فإنه يحدث Exception .

حبذا لو كتبت الـ Exception وأين يحدث حتى يسهل علينا تتبع البرنامج كذلك حبذا لو تضف مشروع البرنامج كاملا حتى يسهل علينا تجربة البرنامج وتتبع الخطأ...

مع تمنياتي لك بالتوفيق

#3
فادي عبدالقادر كتب:

وعليك السلام اخي الكريم

في العادة سبب ذلك يكون عدم ارسال أو استقبال كامل الـ Bytes لملف الصورة وفي العادة يكون السبب في طريقة تحديد Size الـ Buffer عند الإرسال أو الإستقبال ...

حبذا لو كتبت الـ Exception وأين يحدث حتى يسهل علينا تتبع البرنامج كذلك حبذا لو تضف مشروع البرنامج كاملا حتى يسهل علينا تجربة البرنامج وتتبع الخطأ...

مع تمنياتي لك بالتوفيق

ِشكرا أخي فادي على إطلالتك المميزة ...

الصور التالية : توضح نجاح عملية النقل في المرة الاولى ." لكن للأسف تشوه كبير في الصورة "

1-1.jpg

اما هذه الصورة فهي توضح ظهور الخطأ في المرة الثاتية من استدعاء الخدمة :

2-1.jpg

بالنسبة للبرنامج سوف تجده في المرفقات :

Simple Proj.rar

تم تعديل هذه المشاركة بواسطة MKSoft في 26 فبراير 2010 في 10:48

#4

السلام عليكم

المشكلة لديك من هنا في الـ Master Server

                    int size = fileServiceReader.ReadInt32();

                    byte[] buf = new byte[size];

هذه الطريقة لا تستخدم لجلب حجم الملف والذي من المفترض ان يتم ارساله لحجز Buffer عند الإستلام فقط قم بتعديل السطر السابق بكتابة دالة تقرأ الملف ثم تحدد حجمه وسوف يعمل معك بدون مشاكل ...

موفق إن شاء الله

#5
فادي عبدالقادر كتب:

السلام عليكم

المشكلة لديك من هنا في الـ Master Server

                    int size = fileServiceReader.ReadInt32();

                    byte[] buf = new byte[size];

هذه الطريقة لا تستخدم لجلب حجم الملف والذي من المفترض ان يتم ارساله لحجز Buffer عند الإستلام فقط قم بتعديل السطر السابق بكتابة دالة تقرأ الملف ثم تحدد حجمه وسوف يعمل معك بدون مشاكل ...

موفق إن شاء الله

شكرا أخ فادي على المساعدة ... لكن ممكن تفسير أكثر ,, ولو من خلال كود بسيط

وجزاكم ربي خيرا

#6

حسنا قم بتعديل في الـ File Server إلى التالي:

                String filePath = reader.ReadString();
                Console.WriteLine("FilePath := "+filePath);
                byte[] buf = new byte[1280000];
                FileStream fs = new FileStream(filePath, FileMode.Open);
                fs.Read(buf, 0, buf.Length);
                fs.Close();

بدلا من

                byte[] buf = File.ReadAllBytes(filePath);
                int size = buf.Length;

وسيعمل معك بدون مشاكل ايضا

المشكلة التي لديك في دالة تحديد حجم الملف حيث لا تقرأ الدالة ReadAllBytes الملف بشكل صحيح في حالة طلب الملف من خلال السوكيت حيث ترجع الدالة السابقة قيم سالبة في بعض الأحيان في برنامجك للكلينت مما يسبب في الـException السابق حقيقة لم ادقق في سبب ذلك لديك لكن الأفضل استخدام الـ FileStream بدلا منها لأنها مخصصة لهذا الغرض لكن عيبها انها تحتاج إلى تحديد الحد الأقصى لحجم الملف لكنها لا تضر إذ يمكن أن تضع حجم كبير لإرسال أي ملف كما يمكن ان تكتب دالة لقرائة الملف وتحديد حجمه ثم تضعها في الـMax Buffer Size للـFileStream لكني احبذ أن تضع سياسة لحديد الحجم الأقصى للملف لكي لا يؤدي ذلك إلى تهنيج في النظام...

مع تمنياتي لك بالتوفيق

#7

جزاكم ربي خيرا أخ فادي ,, فعلا تم حل المشكلة بالطريقة التي اقترحتها .

اقتباس
لمشكلة التي لديك في دالة تحديد حجم الملف حيث لا تقرأ الدالة ReadAllBytes الملف بشكل صحيح في حالة طلب الملف من خلال السوكيت حيث ترجع الدالة السابقة قيم سالبة في بعض الأحيان في برنامجك للكلينت مما يسبب في الـException السابق

فعلا توضح سبب المشكلة , يبدو أنها في استخدام ReadAllBytes

اقتباس
لكن الأفضل استخدام الـ FileStream بدلا منها لأنها مخصصة لهذا الغرض لكن عيبها انها تحتاج إلى تحديد الحد الأقصى لحجم الملف لكنها لا تضر إذ يمكن أن تضع حجم كبير لإرسال أي ملف

هذا ما دفعني لعدم استخدامها في البداية هو انك تعطيها الحد الأقصى من عدد Bytes ..

لكن عندي سؤال في هذه النقطة أخ فادي ,,

نحن قمنا بحجز أقصى عدد ممكن أو على الأقل حجم كبير نوعا ما , و حجم الملف غالبا أقل من ذلك بكثير , ولذلك الأماكن التخزينية المتبقية في Byte[] buf , ما هي القيم التي تحتويها ؟؟ , وهل تؤثر على طبيعة الملف ؟؟

هل الرقم 1280000 هو أقصى رقم تخزيني , أم هو رقم انت قمت بتقديره ؟؟؟

تم تعديل هذه المشاركة بواسطة MKSoft في 27 فبراير 2010 في 15:25

#8
اقتباس

هذا ما دفعني لعدم استخدامها في البداية هو انك تعطيها الحد الأقصى من عدد Bytes ..

لكن عندي سؤال في هذه النقطة أخ فادي ,,

نحن قمنا بحجز أقصى عدد ممكن أو على الأقل حجم كبير نوعا ما , و حجم الملف غالبا أقل من ذلك بكثير , ولذلك الأماكن التخزينية المتبقية في Byte[] buf , ما هي القيم التي تحتويها ؟؟ , وهل تؤثر على طبيعة الملف ؟؟

هل الرقم 1280000 هو أقصى رقم تخزيني , أم هو رقم انت قمت بتقديره ؟؟؟

اجمالا هذا لا يؤثر ابدا فحجز مقدار معين من الذاكرة امر بسيط مثلا 1280000 بايت يساوي تقريا 1.2 ميجابايت وهي مساحة بسيطة بالذاكرة ويمكنك حجز المقدار الذي تريده بحسب حجم الملف لكن في حالة الملفات الضخمة والتي تزيد عن ذلك بكثير فينصح تقسيم الملف وارساله على اجزاء وذلك من خلال دالة تكرار ترسل في كل مرة حجم معين من الملف حتى نهاية الملف ويقوم المستقبل بترتيب الأجزاء حسب وصولها وهذه الطريقة المستخدمة في كل برامج الـFile Managers وهي الأفضل لكن في حالة كان البرنامج لنقل الصور فبإمكانك المض في هذه الطريقة بدون اي مشكلة ويعتمد ذلك على نوع وحجم الملفات والسياسة المتبعة في النظام الخاص بك...

#9

بارك الله فيك أخي فادي و جزيتم عنا خيرا ..

فعلا الي بيتعامل معكن بيتسفيد

أخوك محمد من غزة

تم تعديل هذه المشاركة بواسطة MKSoft في 28 فبراير 2010 في 00:31

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

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

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

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

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