View Full Version : سوکت نویسی با جاوا
arash.arya43
دوشنبه 16 مرداد 1396, 22:01 عصر
سلام
من سورس جاوا سوکت دارم که درست کار میکنه ولی فقط با لوکال هاست.تمام نت رو گشتم ببینم چه طوری میتونم تنظیم کنم که بشه سرور رو هر کامپیوتری خارج از شبکه اجرا کنم به کلاینت ارتباط پیدا میکنه(منظور با ایپی اینترنتی که با هر بار روشن خاموش کردن مودم یک عدد جدید میشه)
چیزایم که سرچ کردم همگی بروی پورت فورواردینگ بحث شده بود که مون پورت 8888 رو روی مودم فوروارد کردم و فایروالمم خاموشه و برای کار دیگه ای هم استفاده میکنم پس از درست بودنش مطمعنم
لطفا راهنمایی کنین باید چه تغیری تو کد بدم واقعا خسته شدم به سایتهای دیگه خارجی ارجاع ندین plz:افسرده:
کد سرور
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class SimpleFileServer {
public final static int SOCKET_PORT = 13267; // you may change this
public final static String FILE_TO_SEND = "c:/temp/source.pdf"; // you may change this
public static void main (String [] args ) throws IOException {
FileInputStream fis = null;
BufferedInputStream bis = null;
OutputStream os = null;
ServerSocket servsock = null;
Socket sock = null;
try {
servsock = new ServerSocket(SOCKET_PORT);
while (true) {
System.out.println("Waiting...");
try {
sock = servsock.accept();
System.out.println("Accepted connection : " + sock);
// send file
File myFile = new File (FILE_TO_SEND);
byte [] mybytearray = new byte [(int)myFile.length()];
fis = new FileInputStream(myFile);
bis = new BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = sock.getOutputStream();
System.out.println("Sending " + FILE_TO_SEND + "(" + mybytearray.length + " bytes)");
os.write(mybytearray,0,mybytearray.length);
os.flush();
System.out.println("Done.");
}
finally {
if (bis != null) bis.close();
if (os != null) os.close();
if (sock!=null) sock.close();
}
}
}
finally {
if (servsock != null) servsock.close();
}
}
}
کد کلاینت
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class SimpleFileClient {
public final static int SOCKET_PORT = 13267; // you may change this
public final static String SERVER = "127.0.0.1"; // localhost
public final static String
FILE_TO_RECEIVED = "c:/temp/source-downloaded.pdf"; // you may change this, I give a
// different name because i don't want to
// overwrite the one used by server...
public final static int FILE_SIZE = 6022386; // file size temporary hard coded
// should bigger than the file to be downloaded
public static void main (String [] args ) throws IOException {
int bytesRead;
int current = 0;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
Socket sock = null;
try {
sock = new Socket(SERVER, SOCKET_PORT);
System.out.println("Connecting...");
// receive file
byte [] mybytearray = new byte [FILE_SIZE];
InputStream is = sock.getInputStream();
fos = new FileOutputStream(FILE_TO_RECEIVED);
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();
System.out.println("File " + FILE_TO_RECEIVED
+ " downloaded (" + current + " bytes read)");
}
finally {
if (fos != null) fos.close();
if (bos != null) bos.close();
if (sock != null) sock.close();
}
}
}
vahid-p
دوشنبه 16 مرداد 1396, 23:08 عصر
اگر رو لوکال جواب میده مشکل از کد نیست.
الان حضور ذهن ندارم ولی فکر میکنم دو راه وجود داره: اول اینکه سرور دارای آی پی استاتیک باشه. اگر میخواد بین هر دو کامپیوتری باشه، شما باید راهی داشته باشید که آی پی و پورت نگاشت شدتون رو در اینترنت عمومی بدونید. برای اینکار باز نیاز به یک سرور هست. مثلا یک سرور که خیلی ساده توسط برنامه جاواتون بهش ریکوئست بزنید و اون شماره آی پی و شماره پورت رو براتون بفرسته. از اون بتونید استفاده کنید. اگر یک هاست رایگان حتی داشته باشید که بتونه کد پی اچ پی رو اجرا کنه کفایت میکنه (قبلش باید ببینید میتونید port پکت tcp رو با پی اچ پی بگیرید).
البته انتظار داشتم چنین چیزی در اینترنت موجود باشه، و سایت https://www.ipify.org متاسفانه فقط ip رو بر میگردونه. اگر سایتی پیدا کنید که ip و port رو برگردونه شاید جواب بده.
یا هم کلا سرور هر کلاینت به سرور وصل بشه و سرور پیام ها رو بین کلاینت ها انتقال بده
vahid-p
دوشنبه 16 مرداد 1396, 23:29 عصر
روش گرفتن ip و port هم جواب نمیده. این کد php رو تست کردم:
<?php echo $_SERVER['REMOTE_ADDR'].':'.$_SERVER['REMOTE_PORT'];?>
ولی شماره پورت سریع عوض میشه. نمیدونم اینکه یک دانلود منیجر ساعت ها میتونه از یک سرور اطلاعات بگیره شماره پورتش عوض میشه یا نه.
متاسفانه جزئیات کارکرد NAT رو فراموش کردم، بهتره بخونید ببینید اصلا این راه شدنیه و یک سرور چطور مدت ها میتونه به یک کلاینت وصل باشه (مثلا سوکت هم بزنی به سرور، پورت چی میشه تو اون مدت). اگر این راه جواب نده، باید یک سرور بین دو کلاینت داشته باشید که پیام ها رو رد و بدل کنه و از این جزئیات راحت بشید.
arash.arya43
دوشنبه 16 مرداد 1396, 23:42 عصر
روش گرفتن ip و port هم جواب نمیده. این کد php رو تست کردم:
<?php echo $_SERVER['REMOTE_ADDR'].':'.$_SERVER['REMOTE_PORT'];?>
ولی شماره پورت سریع عوض میشه. نمیدونم اینکه یک دانلود منیجر ساعت ها میتونه از یک سرور اطلاعات بگیره شماره پورتش عوض میشه یا نه.
متاسفانه جزئیات کارکرد NAT رو فراموش کردم، بهتره بخونید ببینید اصلا این راه شدنیه و یک سرور چطور مدت ها میتونه به یک کلاینت وصل باشه (مثلا سوکت هم بزنی به سرور، پورت چی میشه تو اون مدت). اگر این راه جواب نده، باید یک سرور بین دو کلاینت داشته باشید که پیام ها رو رد و بدل کنه و از این جزئیات راحت بشید.
کار نکردم :خجالت:
اگر رو لوکال جواب میده مشکل از کد نیست.
الان حضور ذهن ندارم ولی فکر میکنم دو راه وجود داره: اول اینکه سرور دارای آی پی استاتیک باشه. اگر میخواد بین هر دو کامپیوتری باشه، شما باید راهی داشته باشید که آی پی و پورت نگاشت شدتون رو در اینترنت عمومی بدونید. برای اینکار باز نیاز به یک سرور هست. مثلا یک سرور که خیلی ساده توسط برنامه جاواتون بهش ریکوئست بزنید و اون شماره آی پی و شماره پورت رو براتون بفرسته. از اون بتونید استفاده کنید. اگر یک هاست رایگان حتی داشته باشید که بتونه کد پی اچ پی رو اجرا کنه کفایت میکنه (قبلش باید ببینید میتونید port پکت tcp رو با پی اچ پی بگیرید).
البته انتظار داشتم چنین چیزی در اینترنت موجود باشه، و سایت https://www.ipify.org متاسفانه فقط ip رو بر میگردونه. اگر سایتی پیدا کنید که ip و port رو برگردونه شاید جواب بده.
یا هم کلا سرور هر کلاینت به سرور وصل بشه و سرور پیام ها رو بین کلاینت ها انتقال بده
اون مشکلی نداره میشه از دی ان اس استفاده کرد الانم میکنم و بدون مشکل کار میکنه ولی روی این کد جواب نمیده حتی ایپی که الان تو نتم با دستور my ip بدست میارم و ست میکنم.اگه دقت کنی کد سرور اصلا دستوری برای وصل شدن به یک ایپی نداره
vahid-p
سه شنبه 17 مرداد 1396, 11:24 صبح
درسته کد سرور خودش به کسی متصل نمیشه و کلاینت به اون متصل میشه. شما گفتید با وجود اینکه ip عمومی در اینترنت رو جایگزین میکنید باز هم جواب نمیده، خب چون ip کفایت نمیکنه و port رو هم باید بدونید. نقش دی ان اس رو متوجه نشدم. اگر سرورتون یک ip استاتیک داره که مشکلی نداره ولی اگر ip استاتیک ندارید و یک کامپیوتر معمولی تو شبکه هست، چطور میخواید port اش رو بدونید؟
الان تو کدتون port در کلاینت رو برابر port در سرور گرفتید. در صورتی که در شبکه عمومی اینطور نیست و port سرور هر لحظه ممکنه تغییر کنه هر چند روی کامپیوترتون ثابت باشه.
در تصویر زیر میبینید ip و port روی لوکال به ip و port دیگه ای در اینترنت عمومی نگاشت میشه: (شما ip رو دارید، port چی؟)
https://microchip.wdfiles.com/local--files/tcpip:nat-translation-table/nat_table.JPG
arash.arya43
سه شنبه 17 مرداد 1396, 11:39 صبح
وحید جان پورت هر چی باشه برنامه خودش یه ارجا از اون رو برمیگردوه به پرتی که ما تو سرورمون مد نظر کردیم اصلا مشکلی نداره.برنامهای p2p کار کردین؟دقیقا با یک پورت و ایپی میشه بهم وصل شد و چت کرد یا کار دیگه
و سایتهایی مثل no-ip که ثبت نام میکنی و یه دی ان اس میسازی و درون برنامت به جای ایپی ادرس دی ان اس رو میزاری(ادرس دی ان اس یک ایپی ثابته )که سایت no ip میاد نقش یک ایپی ثابت رو برامون ایجاد میکنه .خیلی راحت خیلی روان .الانم دارم استفاده میکنم ازش
vahid-p
سه شنبه 17 مرداد 1396, 12:02 عصر
وحید جان پورت هر چی باشه برنامه خودش یه ارجا از اون رو برمیگردوه به پرتی که ما تو سرورمون مد نظر کردیم اصلا مشکلی نداره
خیلی خلاصه نوشتید، متوجه نشدم چی گفتید.
دقیقا با یک پورت و ایپی میشه بهم وصل شد و چت کرد یا کار دیگه
پست دوم گفتم که ip/port عمومی رو بدونیم میتونیم وصل بشیم. ولی متاسفانه خروجی کد php که نوشتم به ازای هر request به سرور، port عمومی ما عوض میشه (در صورتی که چندان منطقی به نظر نمیاد، شاید هم کدی که نوشتم port واقعی رو نمیده و منو به اشتباه انداخته). البته مستندات NAT (https://tools.ietf.org/html/rfc6886)یه نگاه انداختم مثل اینکه میشه Requested Port Mapping Lifetime رو تنظیم کرد (هر چند ممکنه عدد دلخواه ما رو قبول نکنه) اما چطوریش رو نمیدونم. اگر port عوض نمیشه یا من اشتباه فکر میکنم عوض میشه، خب مشکلی وجود نداره. شما اگر از این موضوع اطلاع دارید خب چرا توضیح نمیدید؟
دی ان اس هم که برای جایگزین کردن اسم به جای ip هست. برا همین میگم نقشش رو متوجه نشدم. الان شما تو dns فقط ip عمومی رو میدید یا ip و port؟!
vahid-p
سه شنبه 17 مرداد 1396, 12:03 عصر
سوال من در مورد ip و port کلاینت نیست. اینکه پورت سرور بیرون از شبکه لوکال چی هست برام جای سواله
vahid-p
سه شنبه 17 مرداد 1396, 12:10 عصر
مشکل از کد php هست که نوشتم. دقت نکردم $_SERVER['REMOTE_PORT'] در اصل port روی ماشین local رو میده نه port ای که نگاشت شده :لبخند:
برای همین local به ازای هر request از یک port آزاد و جدید استفاده میکنه و فکر کردم هی تغییر میکنه.
الان میمونه ساده ترین راهی که بشه port و ip سرور در شبکه عمومی اینترنت رو بعد از راه اندازی ServerSocket بدست آورد. شما میگید اینش مسئله ای نیست، چطور بدست آوردید؟ یعنی ip و port ای که تو NATtable روی gateway قرار میگیره رو چطور بدست میارید؟
و
vahid-p
سه شنبه 17 مرداد 1396, 13:00 عصر
اپلیکیشن های p2p هم با اینکه در ظاهر بدون هیچ واسطی ارتباط برقرار میکنن باز هم مثل اینکه نیاز به یک سرور لااقل برای شناسایی ip/port عمومی دارند.
این سایت که انواع استاندارد ها و پروتکل ها رو معرفی میکنه و جزئیاتش رو میگه انواع روش های p2p رو گفته وقتی که NAT وجود داره:
https://tools.ietf.org/html/rfc5128#section-3
این صفحه 7 هست تا چهار پنج صفحه بعدش بخونید. همشون یک سرور میانی وجود داره که در یکی از روش ها تمامی پیام ها رو سرور بین دو کلاینت جابه جا میکنه (مثل تلگرام و...) و در برخی روش ها فقط راه انداز هست و یا اگر کانکشن قطع شد دوباره بتونه دو کلاینت رو به هم متصل کنه. فقط نمیدونم در روش دوم فایروال جلوگیری میکنه یا نه. به هر حال تو همه روش ها سرور ( دارای ip استاتیک و عمومی) وجود داره
arash.arya43
سه شنبه 17 مرداد 1396, 13:00 عصر
مشکل از کد php هست که نوشتم. دقت نکردم $_SERVER['REMOTE_PORT'] در اصل port روی ماشین local رو میده نه port ای که نگاشت شده :لبخند:
برای همین local به ازای هر request از یک port آزاد و جدید استفاده میکنه و فکر کردم هی تغییر میکنه.
الان میمونه ساده ترین راهی که بشه port و ip سرور در شبکه عمومی اینترنت رو بعد از راه اندازی ServerSocket بدست آورد. شما میگید اینش مسئله ای نیست، چطور بدست آوردید؟ یعنی ip و port ای که تو NATtable روی gateway قرار میگیره رو چطور بدست میارید؟
و
بدست اوردنش رو بیخیال فقط سورسی که دادم چه طوری به ایپی یا ادرس دی ان اسی که دارم وصل بشه تو سورس سرور هیچ کدی مبنی بر وصل شدن به یک ایپی خاص نیست:گریه:
vahid-p
سه شنبه 17 مرداد 1396, 13:09 عصر
بدست اوردنش رو بیخیال فقط سورسی که دادم چه طوری به ایپی یا ادرس دی ان اسی که دارم وصل بشه تو سورس سرور هیچ کدی مبنی بر وصل شدن به یک ایپی خاص نیست:گریه:
بی خیال چیه؟ من کاری به سورس سرور ندارم. مثل اینکه متوجه مسئله نیستید.
ولی تو سورستون وصل شدن به یک آی پی خاص هست، چرا نیست؟ سورس کلاینت نوشتید به سرور با ip لوکال 127.0.0.1 وصل بشه (خب در عمل حتما این عدد رو عوض کردید چون سرورتون همون کامپیوتر نیست، هر چند بهتر بود نمونه عملیش رو میذاشتید نه این کد که ip لوکال داره)
و باز هم میگم ip عمومی برای اتصال کفایت نمیکنه و باید port ای که توسط NAT نگاشت شده، مشخص باشه. (مگر اینکه سرورتون ip استاتیک داشته باشه ولی تو پست اول گفتید "سرور رو هر کامپیوتری خارج از شبکه اجرا کنم" پس یعنی private ip داره و ip ایش از بیرون شبکه محلی همون gateway ip هست.)
الان مشکل اینه کلاینت ip/port نگاشت شده سرور رو نمیدونه. شما میگید تو سورس سرور ip نیست! خب منم میگم کلاینت نمیدونه، چیکار به سورس سرور داره
شما لینکی که دادم رو بخونید تا ببینید مشکل چیه. اصلا بحث دی ان اس اینا نیست. چیزی که من از NAT میدونم اینه.
شما از عملکرد NAT اطلاع دارید؟
اگر فکر میکنید اشتباه میگم، کمک دیگه ای از دست من بر نمیاد. باید از کسی که تخصصش شبکه هست بپرسید تا مطمئن بشید نه در انجمن جاوا.
arash.arya43
سه شنبه 17 مرداد 1396, 15:00 عصر
مشکل از کد php هست که نوشتم. دقت نکردم $_SERVER['REMOTE_PORT'] در اصل port روی ماشین local رو میده نه port ای که نگاشت شده :لبخند:
برای همین local به ازای هر request از یک port آزاد و جدید استفاده میکنه و فکر کردم هی تغییر میکنه.
الان میمونه ساده ترین راهی که بشه port و ip سرور در شبکه عمومی اینترنت رو بعد از راه اندازی ServerSocket بدست آورد. شما میگید اینش مسئله ای نیست، چطور بدست آوردید؟ یعنی ip و port ای که تو NATtable روی gateway قرار میگیره رو چطور بدست میارید؟
و
بدست اوردنش رو بیخیال فقط سورسی که دادم چه طوری به ایپی یا ادرس دی ان اسی که دارم وصل بشه تو سورس سرور هیچ کدی مبنی بر وصل شدن به یک ایپی خاص نیست
چیزی که میگی رو پیاده کن نتیجه بگیر منت بذار نشون بده چون من نتونستم:عصبانی++:
vahid-p
سه شنبه 17 مرداد 1396, 20:20 عصر
به جای اینکه پیامتون رو تکرار کنید به سوال من جواب بدید. چند بار تکرار کردید در سورس سرور هیچ کدی مبنی به اتصال به آی پی خاص نیست. من چنین سوالی پرسیدم؟
این کلاینت هست که باید به سرور وصل بشه و کلاینت باید آی پی و پورت سرور رو بدونه، نه سرور! پس به جای اون 127.0.0.1 که تو کد کلاینت گذاشتید باید ip سرور باشه!
اما به این سوالم پاسخ ندادید:
شما از عملکرد NAT اطلاع دارید؟
اگر نمیدونید لازمه این رو بدونید تا متوجه حرفای من بشید. پس دربارش بخونید.
بعد که اونا رو خوندید، برای راهنمایی میگم، اگر میخواید دو کامپیوتر خارج از شبکه محلی (یکی در ایران یکی در آمریکا) رو بهم وصل کنید، راحتترین راه اینه یک سرور واقعی (با ip ثابت داشته باشید) و پیام های یک کلاینت رو بگیره و به کلاینت دیگه ارسال کنه. یا هم همون مسائلی که توضیح دادم و تکرارش نمیکنم چون قبلش باید بدونید NAT چی هست و چه مشکلی رو ایجاد میکنه.
فکر میکنم انواع حالات و مشکلات موجود رو گفتم، اگر متوجه نمیشید حتما پایه اش رو نمیدونید یا هم من دارم اشتباه میگم. از این دست پروژه ها هم فراوان کدش وجود داره، کافیه سرچ کنید chat application in java.
اینم یه آموزش ویدیویی 16 دقیقه ای https://www.youtube.com/watch?v=kqBmsLvWU14
در جواب سوال پست اولتون که
بشه سرور رو هر کامپیوتری خارج از شبکه اجرا کنم
باید ip استاتیک از isp خریداری کنید.
موفق باشید.
arash.arya43
پنج شنبه 28 دی 1396, 00:50 صبح
به جای اینکه پیامتون رو تکرار کنید به سوال من جواب بدید. چند بار تکرار کردید در سورس سرور هیچ کدی مبنی به اتصال به آی پی خاص نیست. من چنین سوالی پرسیدم؟
این کلاینت هست که باید به سرور وصل بشه و کلاینت باید آی پی و پورت سرور رو بدونه، نه سرور! پس به جای اون 127.0.0.1 که تو کد کلاینت گذاشتید باید ip سرور باشه!
اما به این سوالم پاسخ ندادید:
اگر نمیدونید لازمه این رو بدونید تا متوجه حرفای من بشید. پس دربارش بخونید.
بعد که اونا رو خوندید، برای راهنمایی میگم، اگر میخواید دو کامپیوتر خارج از شبکه محلی (یکی در ایران یکی در آمریکا) رو بهم وصل کنید، راحتترین راه اینه یک سرور واقعی (با ip ثابت داشته باشید) و پیام های یک کلاینت رو بگیره و به کلاینت دیگه ارسال کنه. یا هم همون مسائلی که توضیح دادم و تکرارش نمیکنم چون قبلش باید بدونید NAT چی هست و چه مشکلی رو ایجاد میکنه.
فکر میکنم انواع حالات و مشکلات موجود رو گفتم، اگر متوجه نمیشید حتما پایه اش رو نمیدونید یا هم من دارم اشتباه میگم. از این دست پروژه ها هم فراوان کدش وجود داره، کافیه سرچ کنید chat application in java.
اینم یه آموزش ویدیویی 16 دقیقه ای https://www.youtube.com/watch?v=kqBmsLvWU14
در جواب سوال پست اولتون که
باید ip استاتیک از isp خریداری کنید.
موفق باشید.
چند سورس دیدم اصلا به یه خط دو خط کد این درست بشو نیست .کلی مکافات داره موفق باشی
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.