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

مشكلة فى Java Socket

بدأه sameh mahmoud في 6 أكتوبر 2009 · 36 رد · 2,737 مشاهدة · في JavaSE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكــم ورحمـة الله وبركاتــه ،،

لقد شاب شعري من هذه المشكلة ارجو المساعدة

احاول عمل برنامج بسيط لارسال رسالة من الكلينت الى السيرفر ولكن للاسف عندما يأتى سطر القراءة وهو كالتالي :

msge = scan.nextLine();

msge من نوع سترنج

تتوقف حلقات التكرار بدون اي سبب مما يجعلني اعاني من الجنون !!!

الكود السيرفر

package networking;

import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.net.UnknownHostException;
import java.io.PrintWriter;
import java.util.Scanner;

 

public class SamehServer
{
	private int port;
	private ServerSocket serSoc;
	private Socket soc;
	private String message;


   SamehServer(int portnum)
   {
	   this.port = portnum;
	   String msg1;

	   try
	   {
		 serSoc = new ServerSocket(port);

	   }
	   catch(IOException e)
	   {
		   e.printStackTrace();
	   }

	   if(true)
	   {
			try {
				soc = serSoc.accept();
			} catch (IOException ex) {

			}
			for(;;)
			 getMessage();
	   }



   }



   void sendMessage(String msg)
   {
	   try
	   {
		   PrintWriter print = new PrintWriter(soc.getOutputStream());

			   print.println(msg);

		   soc.close();
	   }
	   catch(UnknownHostException e)
	   {
		   e.printStackTrace();
	   }
	   catch(IOException e)
	   {
		   e.printStackTrace();
	   }
   }

   void getMessage()
   {
	  try
	   {		   
		   Scanner scan = new Scanner(soc.getInputStream());
		   String msge = scan.nextLine();
			   msge = scan.nextLine();
			   System.out.println(msge);

	   }
	   catch(UnknownHostException e)
	   {
		   e.printStackTrace();

	   }
	   catch(IOException e)
	   {
		   e.printStackTrace();

	   }
   }

  public String getIncomeMessage()
  {
	  return message;
  }
}

كود الكلينت

package networking;

import java.net.Socket;
import java.net.UnknownHostException;
import java.io.IOException;
import java.io.PrintWriter;

public class clientSameh
{
	private String hostName;
	private int portNum;
	private Socket soc;

	clientSameh(String host , int port)
	{
		this.hostName = host;
		this.portNum = port;
		try
		{
		   soc = new Socket(hostName , portNum);
		}
		catch(UnknownHostException e)
		{
			e.printStackTrace();
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
	}

	void sendMessage(String msg)
	{
	   try
		{
		   // soc = new Socket(hostName , portNum);
		   PrintWriter pr = new PrintWriter(soc.getOutputStream() , true);
		   pr.println(msg);
		}
		catch(UnknownHostException e)
		{
			e.printStackTrace();
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
	}


}

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#4

أنت في كل مرة تقوم بإنشاء Stream جديد , و هذا غير منطقي ,, لذلك جرب وضع Scanner scan = new Scanner(soc.getInputStream());

في خارج الدالة getMessage , وهكذا بإذن الله يعمل البرنامج.

تم تعديل هذه المشاركة بواسطة MKSoft في 6 أكتوبر 2009 في 11:09

#5

السلام عليكم

اولا الاخ محمد مشاري : الميثود فى بالفعل فى حلقة تكرار لا نهائية

for(;;)
getMessage();

ثانيا الاخ MKSoft : لقد فعلت ما قلت و لأسف لا يوجد نتيجة

اصبح الكود الخاص بالسيرفر هكذا

package networking;

import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
import java.net.UnknownHostException;
import java.io.PrintWriter;
import java.util.Scanner;



public class SamehServer
{
	private int port;
	private ServerSocket serSoc;
	private Socket soc;
	private String message;
	private Scanner scan;

   SamehServer(int portnum)
   {
	   this.port = portnum;
	   String msg1;

	   try
	   {
		 serSoc = new ServerSocket(port);

	   }
	   catch(IOException e)
	   {
		   e.printStackTrace();
	   }

	   if(true)
	   {
			try {
				soc = serSoc.accept();
				scan = new Scanner(soc.getInputStream());
			} catch (IOException ex) {

			}
			for(;;)
			 getMessage();
	   }



   }



   void sendMessage(String msg)
   {
	   try
	   {
		   PrintWriter print = new PrintWriter(soc.getOutputStream());

			   print.println(msg);

		   soc.close();
	   }
	   catch(UnknownHostException e)
	   {
		   e.printStackTrace();
	   }
	   catch(IOException e)
	   {
		   e.printStackTrace();
	   }
   }

   void getMessage()
   {
//	  try
//	   {

		   String msge = scan.nextLine();
			   System.out.println(msge);

//	   }
//	   catch(UnknownHostException e)
//	   {
//		   e.printStackTrace();
//
//	   }
//	   catch(IOException e)
//	   {
//		   e.printStackTrace();
//
//	   }
   }

  public String getIncomeMessage()
  {
	  return message;
  }
}

تم تعديل هذه المشاركة بواسطة sameh mahmoud في 6 أكتوبر 2009 في 12:11

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#6

المشكلة ان الرسالة تأتى مرة واحدة فقط ,

و عند كتابة رسالة اخرى لا تأتى اطلاقا

لماذا !!!!!!!! :blink:

تم تعديل هذه المشاركة بواسطة sameh mahmoud في 6 أكتوبر 2009 في 12:14

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#7

الملفات كمرفق يا سامح

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#8

أرنا الmain لنرى كيف تستعمل هاتين الفئتين

لاحظ في هذين السطرين


msge = scan.nextLine();
String msge = scan.nextLine();

فأنت تقرأ مرتين وتخزن في نفس المتغير، ما يعني أن القيمة الأولى تضيع

#9

السلام عليكــم ورحمـة الله وبركاتــه

الاخ عصام و علاء انا اسف جدا انا ارتكبت خطأ شنيع فى ال Main و تم حل المشكلة و الحمد لله

و بخصوص

String msge = scan.nextLine();
   msge = scan.nextLine();

جائت بدون قصد :unsure:

بعد ان تم حل المشكلة , احاول ان اقم بعمل خاصية نقل الملفات اثناء المحادثة ولكن تواجهني مشكلة حيث سيتم شفط ال data الخاصة بالمحادثة و ال data الخاصة بالملف من استريم واحد

مما يبطئ عملية نقل الملف اثناء المحادثة .

فهل يوجد فكرة لحل هذه المشكلة ؟؟؟؟ وشكرا جدا

المشروع فى المرفقات

Transporter.rar

تم تعديل هذه المشاركة بواسطة sameh mahmoud في 6 أكتوبر 2009 في 20:24

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#10

استخدم

java.nio.channels

ونسخ الملف

public class FileCopy {
private FileChannel source ,dest;
private long pos;
public FileCopy(String src ,String des) throws IOException {
source=(new FileInputStream (src)).getChannel();
dest=(new FileOutputStream(des)).getChannel();
pos=0;
dest.transferFrom(source,pos,source.size());
dest.close();
}

اضن انها ناجحة

بالتالي تبتعد عن موضوع المحادثة ببرنامجك ... يبقى تحديد المصدر والجهة في الmain

على فكرة جربت البرنامج وما صار تحدث بينيـ وبين حاليـ :P

#11

شكرا يا اخ شادو على التوضيح

و البرنامج اللى عندك لا يعمل لانك اخذت السيرفر فقط و ليس الكلينت و السيرفر معا , و لكن الاختلاف بينهما فى الدالة Main فقط

العميل فى المرفقات

سأجرب ماقلت لى و اعود

Transporter.rar

تم تعديل هذه المشاركة بواسطة sameh mahmoud في 7 أكتوبر 2009 في 13:29

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#12

ياريت يا حج شادى او اى شخص اخر تلصق الكود فى المكان الصح عشان انا مش فاهم

جزاك الله كل خير

المشروع فى المرفقات

Transporter.rar

انا عارف ان المشروع ملغبط و فى غاية من عدم الترتيب

انا اسف جدا

تم تعديل هذه المشاركة بواسطة sameh mahmoud في 11 أكتوبر 2009 في 02:30

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#13

BUZZ

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#14

منتظر الرد

BUZZ

!!!!!

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#15

BUZZ !!

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#16

بأمانة خمس دقائق وأنا أفتش في الشيفرة

تكلم عن برنامجك أخ سامح

تريدني أن أساعدك ساعدني على أن أساعدك

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#17

شكرا يا بشمهندس علاء على الرد

و انا اسف على التأخير

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

البرنامج به 2 كلاس اساسيتان الاول : ServerMan و هى فى حالة ان المستخدم اراد ان يكون سيرفر , و الكلاس الثانية ClientSameh و هى فى حال اراد المستخدم ان يكون عميل , و يوجد به Interface

تسمى SocketSamehListener و هى تمثل احداث الكلاسين السابقين ( اتصال - ارسال رسالة - اغلاق الاتصال ) و يتم ربط هذه الواجهة بالكلاس فى الميثود setListener

	 void setListener(SocketSamehListener s)
	 {		
		 sml = s;
		 hasListener = true;
	 }

sml هو اوبجكت من الانترفيس SocketSamehListener و سيتم تنفيذ الميثود فى الكلاس GUI

serMan.setListener(new SocketSamehListener()
						{
							   public void RequestReciceFile()
							   {

							   }
							   public void FileIncoming(String name , int data)
							   {

							   }

							   public void Connected()
							   {
								  System.out.println("Connected !");
								  serMan.FileSendRequest("d:/sameh.mp3");
							   }
							   public void MessageRecived(String message)
							   {
									  msr.readMessage(message);
							   }
						});

لنفترد اننا استخدمنا الكلاس serverMan :

عندما تتم عملية الاتصال يتم اطلاق thread جديد لتكرار تنفيذ الميثود ReciveData و ليتمكن البرنامج من ارسال بيانات مع الاستقبال فى نفس الوقت عن طريق ال thread الاساسي , و فى حال اننا وضعنا المستمع لهذا الكلاس ( SocketSamehListener ) يتم تنفيذ الميثود Connect الموجودة فى هذه الواجهة

	 public void run()
	 {
		 if(hasListener == true)
			 sml.Connected();
		 for(;;)
		  ReciveData();
	 }

و يمكن ايضا ارسال رسالة عن طريق الميثود sendStringMessage

	 void sendStringMessage(String msg)
	 {
		 pr.println(msg);
	 }

pr هو Object من الكلاس PrintWriter

نأتى للميثود ReciveData

	 private void ReciveData()
	  {
		   messageIncome = scan.nextLine();
		   if(messageIncome.equals(GetFileRequest))
		   {
			   allowSendFile = true;
				 sendFile("d:/sameh.mp3");
		   }
		   System.out.println("Message Recived " + messageIncome);
		   if(hasListener == true)
			 sml.MessageRecived(messageIncome);			 
	  }

تم تعديل هذه المشاركة بواسطة sameh mahmoud في 15 أكتوبر 2009 في 02:28

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#18

الان اريد عمل امكانية نقل الملفات بين السيرفر و العميل , و لكن للاسف سيتم استخدام InputStream واحد لعملية نقل الملف و المحادثة معا مما يبطئ عملية النقل

اذا اردنا ان نرسل ملف معين لابد ان يوافق الكلينت على ارسال هذا الملف فنقوم بأرسال استأذان للعميل بأرسال الملف عن طريق الميثود FileSendRequest و تأخذ معامل نصى يمثل اسم الملف

تقوم هذه الميثود بأرسال رسالة ذات حروف خاصة للعميل و عندما تصل هذه الحروف الخاصة للعميل يقوم هو بأرسال امر بالموافقة عن طريق الثابت GetFileRequest الذى يمثل الموافقة

لندع الكود يتحدث :

فى السيرفر - فى حالة ارسال استأذان بأرسال الملف

تقوم هذه الميثود بأرسال الحروف الخاصة الى العميل هذه الحروف الخاصة هى الثابت sendingFileRequest + اسم الملف

	 public void FileSendRequest(String filename)
	 {
		 String fileReqPro = sendingFileRequest + filename;
			 pr.println(fileReqPro);
	 }

و الان مع العميل

فى الميثود ReciveData الموجودة فى ClientSameh اذا كانت الرسالة القادمة تحتوى على الحروف الخاصة (sendingFileRequest) و بهذ نعرف ان السيرفر ارسل استأذان بأن يرسل للعميل ملف

يتم تنفيذ الميثود RequestReciveFile الموجودة فى الواجهة SocketSamehListener و عند عمل override لهذه الطريقة نقوم بأرسال امر الموافقة (الثابت GetFileRequest)

	  private void ReciveData()
	  {
		  message = scan.nextLine();
		  if(hasListener)
			sml.MessageRecived(message);
		  if(hasListener == true && message.startsWith(sendingFileRequest))
			sml.RequestReciceFile();
		  System.out.println(message);
	  }

sml هنا هى اوبجكت من الانترفيس SocketSamehListener و تم تنفيذها فى الكلاس GUI

					  cls.setListener(new SocketSamehListener()
					  {
						  public void RequestReciceFile()
						  {
							  System.out.println("We are requested");
						  }
						  public void FileIncoming(String name , int data)
						  {

						  }
						  public void Connected()
						  {
							System.out.println("Connected !");
						  }

						  public void MessageRecived(String message)
						  {
							 msr.readMessage(message);
						  }
					  });

فى حالة ان العميل مواقف على استلام الملف من السيرفر يقوم بأرسال الثابت GetFileRequest

						  public void RequestReciceFile()
						  {
							  System.out.println("We are requested");
							  cls.SendStringMessage(ClientSameh.GetFileRequest);
						  }

cls هو اوبجكت من الكلاس ClientSameh

تم تعديل هذه المشاركة بواسطة sameh mahmoud في 15 أكتوبر 2009 في 13:14

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#19

فى حال ارسال العميل امر بالموافقة على استلام الملف ( الثابت GetFileRequest ) يقوم السيرفر بالميثود sendFile

اولا : الميثود ReciveData الموجودة فى السيرفر

نتحقق من ان الرسالة تحتوى على الثابت GetFileRequest , و فى حالة انها تحتوى على هذا الثابت يتم استخدام الميثود sendFile

	 private void ReciveData()
	  {
		   messageIncome = scan.nextLine();
		   if(messageIncome.equals(GetFileRequest))
		   {
			   allowSendFile = true;
				 sendFile("d:/sameh.mp3");
		   }
		   System.out.println("Message Recived " + messageIncome);
		   if(hasListener == true)
			 sml.MessageRecived(messageIncome);
	  }

المشكلة يا بشمهندس علاء كما قلت لك هى ان ال data الخاصة بالملف و ال data الخاصة بالمحادثة سيتم شفطهما من InputStream واحد و هذا سيبطئ عملية نقل الملف اثناء المحادثة

لذلك تركت لك الميثود sendFile فارغة لتملئها انت

فهل من حل لهذه المشكلة

و جزاك الله كل خير

تم تعديل هذه المشاركة بواسطة sameh mahmoud في 15 أكتوبر 2009 في 03:25

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#20

BUZZ !!

BUZZ !!

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#21

لماذا لا تفتح منفذين واحد للمحادثة والآخر لإرسال الملفات؟؟؟

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#22

سيتم عمل بلوك و سيتم ايقاف البرنامج كله بما فيه المحادثة لحين ان يقبل العميل

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#23

بالطبع ستحتاج إلى فتح خيط جديد لهذه العملية

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#24

علم و جاري التنفيذ

عندما انتهى من البرنامج سوف اضعه هنا .

سبـــــحــــان الله و بحمده سبحان الله العظيم

403100468.gif

#25

شكلك كاين في العسكرية يا سامح :)

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

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