PDA

View Full Version : سوال: کمک در برنامه نویسی سوکت



mojdeh9000
جمعه 12 اردیبهشت 1393, 09:14 صبح
سلام به دوستان...
میشه برای رفع خطای برنامه ام کمک کنید؟؟؟؟
برنامه ام درباره ایجاد ارتباط TCP در مبحث برنامه نویسی سوکته،موقع اجرای کد سمت سرور پیغام java.lang.IllegalThreadStateException میده،اصلا وارد run نخ نمیشه...:افسرده:
118547

mojdeh9000
جمعه 12 اردیبهشت 1393, 10:14 صبح
اون مشکل خطا حل شد برنامه درست را ضمیمه میذارم،فقط یه مشکل دیگه چطوری میشه بین دو سوکت داده ای روی یک سرور داده رد و بدل کرد؟؟؟؟برنامه ام اینجوریه که باید یه کلاینت به پورت9001 داده بفرسته و یک کلاینت دیگه همون داده رو از پورت 9002 بگیره،مشکلم اینه که نمیدونم چطوری داده رو از پورت 9001 به 9002 بفرستم؟؟؟؟118548

cups_of_java
جمعه 12 اردیبهشت 1393, 10:48 صبح
چه فرقی میکنه اون ساکت سرور ساکت باشن یا ساکت روی کلاینت!؟ همون طوری که شما داری بین کلاینت و سرور (مثلن پورت 9001 سرور و پورت 9005 کلاینت) داری داده می نویسی همون کار رو بین دو تا ساکت سرور (یکی 9001 و دیگری 9002) انجام میدی. ساکت، ساکته دیگه!

mojdeh9000
جمعه 12 اردیبهشت 1393, 11:14 صبح
ممنون بابت راهنماییتون فکر کنم حدودا فهمیدم!!!

mojdeh9000
شنبه 13 اردیبهشت 1393, 17:40 عصر
سلام...
مشکلم حل نشده هنوز!!!میشه بیشتر بهم راهنمایی کنید؟؟؟
من برای ارتباط بین سرور و کلاینت اینجوری نوشتم:

ServerSocket connectionSocket = new ServerSocket(serverPortNumber);
Socket dataSocket = connectionSocket.accept();



Socket clientSocket = new Socket(acceptorHost, serverPortNum);
سرور تو متد acceptمنتظرمیمونه هروقت یه کلاینت تقاضا داد اون رو accept میکنه و بعدش هم بااستریم ها داده رد و بدل میکنن....
حلا من میخوام دوتا سرور ساکت که با دوتا کلاینت مجزا ارتباط برقرارکردن باهم دیگه ارتباط برقرارکنن ،به این صورت که مثلن پورت 9001 از کلاینت داده بگیره و هرزمان یه کلاینت تقاضای برقراری ارتباط به پورت 9002 داد این داده که رو پورت 9001 هست به پورت 9002 منتقل بشه(بدون انتظار برای accept).....
ممنون میشم اگه راهنماییم کنید....

mojdeh9000
شنبه 13 اردیبهشت 1393, 18:37 عصر
چطوری میشه مشخص کرد که ساکت کلاینت روی یه پورت خاص ارتباط برقرارکنه مثلا کلاینت باپورت 8000 با سرور با پورت 9000 ارتباط برقرار کنه؟؟؟

vahid-p
شنبه 13 اردیبهشت 1393, 19:15 عصر
تو انجمن JavaEE مطرح کردی، جرئت نمیکنیم جواب بدیم :لبخند:
با اجازه از استاد گرامی cups_of_java (http://barnamenevis.org/member.php?67212-cups_of_java) . چون من خودم خیلی سوال میپرسم و انتظار دارم دوستان کمک کنند، وظیفه ی خودم میدونم که این همه استفاده کردم، تا حد کمی جبران کنم.

فکر کنم همونیه که تو Java Se انجام میشه. کدتون رو نگاه کردم، به نظرم بهتره وقتی یک socket از accept گرفتید، بعدش یه Thread درست کنید تا کارهای send & receive رو انجام بده.
فقط قبل از اینکه بگم، دلیل اینکارتون رو نفهمیدم :
while(true){
th1.start();
th2.start();
}
اینکه نمیذاره اجرا بشه بیچاره؟!
یه بار که start کنید run اجرا میشه دیگه. گرچه جاوا خودش منتظر میمونه Thread ها تموم بشن، ولی محض احتیاط میتونی join هم بنویسی بعدش. ( یعنی صبر کن تا اینا تموم بشن بعد )
پس کلاس Main.java رو اینجوری تغییر میدم :
public class Main {
public static void main(String[] args){
try {
ServerSocket connection1=new ServerSocket(9001);
ServerSocket connection2=new ServerSocket(9002);
server th1=new server(connection1);
srever2 th2=new srever2(connection2);
th1.start();
th2.start();
th1.join();
th2.join();
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.S EVERE, null, ex);
} catch (InterruptedException ex) {
Logger.getLogger(Main.class.getName()).log(Level.S EVERE, null, ex);
}
}
}

بعد اینکه چرا دو کلاس server درست کردی؟! تفاوت خاصی که نداشتن تا جایی که من متوجه شدم. مثلا تو server2.java از
while (i<100) {
استفاده کردی برای محدود کردن تعداد کلاینت ها در صورتی که خواد ServerSocket تو تابع سازندش، این امکان رو داره که تعداد کلاینت ها رو محدود کنی مثلا :
ServerSocket connection2=new ServerSocket(9001,100);
که بیشتر از 100 کلاینت نمیذاره متصل بشن. البته اگر از این کانستراکتوری که شما استفاده کردید و مشخص نکردید به صورت پیش فرض 50 تا در نظر میگیره. ضمنا بخواید راه دور استفاده کنید دیگه localhost نیست و از کانستراکتور سه آرگومانه برای تعیین host استفاده کنید. و در کلاس مخصوص کلاینت هم باید new Socket کنید و پورت رو بهش بدید. چون اینجا Server و Client یه جاست تونستید از socket.accept سوکت لازم برای کلاینت رو هم بگیرید و درگیر تنظیم پورت و... نشید .

شایدم منظورتون از اون 100 یه چیز دیگه بوده که بهتره تو سوالتون شفاف مشخص کنید روند برنامه رو. چون آپلود کردن کل فایل ها و اینکه طرف با خوندن کد بخواد منظور شما رو اول متوجه بشه و بعد هم مشکلاتش رو برطرف کنه کار ساده ای نیست.
من بودم یک کلاس server میسازم و دو آبجکت ازش میگیرم. یعنی تو کد Main به جا srever2 از server استفاده میکنم ( البته از نظر املایی اشتباه داشتید : srever2 )
بقیش که درسته، و اینکه برای کلاس sender هم بهتره از کلاس Scanner استفاده کنید که راحتتره و بهتره باز برای ارسال و دریافت هم دو Thread جداگونه داشته باشی تا بین ارسال و دریافت تداخل ایجاد نشه. مثلا :
package serverchat2;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author Rayan Technic Tehran
*/
public class sender extends Thread{
Socket socket;
Scanner receiver;
Scanner keyboard;
ObjectOutputStream sender;
public sender(Socket socket){
this.socket=socket;
}
@Override
public void run(){
try{
receiver=new Scanner(socket.getInputStream()); //Input from server
keyboard=new Scanner(System.in); //Input from keyboard
sender=new ObjectOutputStream(socket.getOutputStream());
new Thread(new Runnable(){ //From server

public void run() {
String getMsg;
while(true){
getMsg=receiver.next();
System.out.println(getMsg);
}
}
}).start();
new Thread(new Runnable(){ //To server

public void run() {
String sendMsg;
while(true){
sendMsg=keyboard.nextLine();
try {
sender.writeChars(sendMsg);
} catch (IOException ex) {
Logger.getLogger(sender.class.getName()).log(Level .SEVERE, null, ex);
}
}
}
}).start();
}catch(IOException e){
System.err.println("Error in IO!");
}
}
}




راستی یه چیزی یادم نره، اینکه سرور برای کلاینتش هیچی نمیفرسته و در اجرا چیزی نمیبینید. اینا رو هم باید بنویسید. شایدم کلاس sender تون برای سرور بوده که اونوقت نیازی به ارسال کردن ندارید و در نتیجه نیازی به Thread گذاری نیست و تو همون قسمت run سندر میتونید دریافت رو بنویسید. ولی خب شما اینجا کلاسی برای Client ندارید که من متعجب شدم و فکر کردم sender همون کلاینتتون هست!

موفق باشید

vahid-p
شنبه 13 اردیبهشت 1393, 19:28 عصر
اگه sender مربوط به سروره خب همون کد اولی بهتر بود. البته با یکم تغییر میشه این : ( تقریبا همونی که شما نوشتید )
public class sender extends Thread{
Socket socket;

public sender(Socket socket){
this.socket=socket;
}
@Override
public void run(){
try {
String getMsg;
Scanner receiver=new Scanner(socket.getInputStream()); //Input from server

while(true){
getMsg=receiver.next();
System.out.println(getMsg);
}
} catch (IOException ex) {
Logger.getLogger(sender.class.getName()).log(Level .SEVERE, null, ex);
}
}
}


چطوری میشه مشخص کرد که ساکت کلاینت روی یه پورت خاص ارتباط برقرارکنه مثلا کلاینت باپورت 8000 با سرور با پورت 9000 ارتباط برقرار کنه؟؟؟
اگه اینجوری بود که دیگه پورت چه معنی داشت؟ پورت یا همون درگاه با شماره مشخص میشن. یعنی سرور و کلاینت رو پورت مثلا 8000 با هم ارتباط برقرار میکنن. اگه پورت دیگه ای بره که دیگه کاری به کار هم ندارن.
شما برنامه مستقل کلاینت رو بنویسید اگه مشکلی داشتید بذارید اینجا.

cups_of_java
شنبه 13 اردیبهشت 1393, 19:37 عصر
همونطوری که دوستمون گفته شما روی سرور سوکت هایی که داری InputStream , OutputStream می سازی و روشون می نویسی و میخونی. پورت رو هم توی ایجاد سوکت مشخص میکنید.

mojdeh9000
شنبه 13 اردیبهشت 1393, 21:18 عصر
سلام....
واقعا ممنون از توضیحاتتون ...ولی مثل اینکه من فراموش کردم کد سمت کلاینت رو بذارم!!!واقعا ازدوستان معذرت می خوام ولی مشکل من هنوز حل نشده

بهتره تو سوالتون شفاف مشخص کنید روند برنامه رو. چون آپلود کردن کل فایل ها و اینکه طرف با خوندن کد بخواد منظور شما رو اول متوجه بشه و بعد هم مشکلاتش رو برطرف کنه کار ساده ای نیست.حق باشماست من باید هی توضیح کامل بدم درباره کدم،اینم توضیح:
هدف برنامه اینه که یه کلاینت با پورت 9001 ارتباط برقرارکنه و مسیج بذاره و از طرف دیگه کلاینت دیگه ای با پورت 9002 ارتباط برقرارکنه و اون مسیج رو بخونه،بعبارت دیگه پورت9001 وظیفه دریافت پیام و پورت 9002 وظیفه ارسال پیام ها را به عهده دارن،از طرف دیگه چند تا کلاینت باهم میتونن پیام بفرستن رو پورت 9001 و چن تا باهم میتونن پیام ها را از پورت9002 دریافت کنن.

فقط قبل از اینکه بگم، دلیل اینکارتون رو نفهمیدم :
while(true){
th1.start();
th2.start();
}
اینکه نمیذاره اجرا بشه بیچاره؟!
این همون اشتباهی بود که بخاطرش اون پیغام رو میدادکه اول پست گذاشتم نباید حلقه داشته باشه...

بعد اینکه چرا دو کلاس server درست کردی؟! تفاوت خاصی که نداشتن تا جایی که من متوجه شدم. مثلا تو server2.java از
while (i<100) {
استفاده کردی برای محدود کردن تعداد کلاینت ها
دلیل اینکه دوتا کلاس serverدرست کردم این بود که اگر یک کلاینت به عنوان فرستنده متصل بشه بره سراغ server و اگر به عنوان گیرنده باشه بره سراغsrever2(بابت غلط املایی هم معذرت میخوام بعضی وقتا پیش میاد:خجالت:) اون حلقه while هم برای ایجاد محدودیت روی تعداد کلاینت هایی بود که متصل میشن....
اینم کد سمت کلاینت :

Scanner scan = new Scanner(System.in);
System.out.println("please enter localhost:");
String host = scan.next();
System.out.println("please r or s :");
String type = scan.next();
if (type.equalsIgnoreCase("s")) {
try {
Socket clientTOSND = new Socket(host, 9001);
while (true) {
System.out.println("please enter your message :");
Scanner scan2 = new Scanner(System.in);
String message = scan2.nextLine();
PrintStream ps = new PrintStream(clientTOSND.getOutputStream());
ps.println(message);
ps.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (type.equalsIgnoreCase("r")) {
try {
Socket clientTORCV = new Socket(host, 9002);
while (true) {
BufferedReader br = new BufferedReader(new InputStreamReader(clientTORCV.getInputStream()));
String msg = br.readLine();
System.out.println(msg);

}
} catch (Exception e) {
e.printStackTrace();
}
}
حالا مشکلم اینه که مسیجی که تو کلاس sender ارسال میشه چطوری کلاس reciever اونو دریافت کنه؟؟؟؟
برنامه تو خط
BufferedReader br = new BufferedReader(new InputStreamReader(arr[i].getInputStream()));
String msg = br.readLine();بلاک میشه چون هیچ مسیجی رو پورت 9002 فرستاده نشده!!!
حلا چطوری مسیجی که تو خط
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println(msg);بفرستم براش؟؟؟؟؟
118605

vahid-p
شنبه 13 اردیبهشت 1393, 21:48 عصر
نیازی به تعریف دو پورت جدا برای ارسال و دریافت اطلاعات ندارید. خودتون رو درگیر این موضوع نکنید. اینکه رو یک کامپیوتر دو سرورسوکت اون هم فقط برای ارسال و دریافت باشه به نظرم ضرورتی نداره و کارتو پیچیده میکنه.حالا مثلا هر پورت مخصوص خدمات خاصی بود درست.

سعی کنید ساده تر باهاش برخورد کنید، اگه نتونستید، فردا سعی میکنم یه نمونه ساده و کامل رو بذارم و اونو بنا به نیازتون گسترش بدید. البته صد در صد تو اینترنت نمونه های زیادی هستند. مثلا بنویس simple server client connection in java حتما نتایج به درد بخوری داره.

mojdeh9000
شنبه 13 اردیبهشت 1393, 22:11 عصر
نیازی به تعریف دو پورت جدا برای ارسال و دریافت اطلاعات ندارید. خودتون رو درگیر این موضوع نکنید. اینکه رو یک کامپیوتر دو سرورسوکت اون هم فقط برای ارسال و دریافت باشه به نظرم ضرورتی نداره و کارتو پیچیده میکنه.حالا مثلا هر پورت مخصوص خدمات خاصی بود درست.

سعی کنید ساده تر باهاش برخورد کنید، اگه نتونستید، فردا سعی میکنم یه نمونه ساده و کامل رو بذارم و اونو بنا به نیازتون گسترش بدید. البته صد در صد تو اینترنت نمونه های زیادی هستند. مثلا بنویس simple server client connection in java حتما نتایج به درد بخوری داره.
این یه پروژه درسیه که اینجوری تعریف شده!....
بازم ممنون اگه پیداش کردم حتما کدش رومیذارم.

mojdeh9000
سه شنبه 16 اردیبهشت 1393, 22:04 عصر
سلام
دوستان جواب سوالم رو پیداکردم:لبخندساده:
برای اینکه مسیج را از یه پورت روی سرور به پورت دیگه منتقل بشه فقط کافیه جریان خروجی طرف ارسال کننده را در طرف گیرنده قراربدیم و بعد اون رو از جریان خروجی بخونیمش...به همین راحتی!!!:چشمک:
اگر کسی توضیحات بیشتر خواست درخدمتم....