ورود

View Full Version : سوال: برنامه ارسال و گرفتن عکس در جاوا با استفاده از سوکت



staaaaaar
دوشنبه 29 دی 1393, 19:45 عصر
سلام خدمت اساتید
میخواستم دوتا برنامه تو جا وا بنویسم ک یکی server و دیگری client ک از صفحه نمایش عکس بگیره و به client بفرسته سوالم اینجاست ک چطوری با استفاده
از socket این کار رو بکنم . کمکم کنید ممنون میشم
با تشکر

ahmad.mo74
دوشنبه 29 دی 1393, 21:28 عصر
سلام

برای گرفتن اسکرین شات از کلاس Robot میشه استفاده کرد :


Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSiz e()));


Robot برای عکس گرفتن از صفحه یک Rectangle ازمون میخواد که ما هم یه مستطیل به طول و عرض صفحه نمایش (دلخواه) بهش میدیم.

برای اینکه این عکس رو بفرستیم نیاز به یک سرور هست که روی پورتی listen کنه و هروقت عکس رسید اونو در محلی که گفتیم ذخیره کنه.

ScreenUtil :


package com.sample.util;


import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;


/**
* @author avb
*/
public class ScreenUtil {


public static byte[] takeScreenShot() throws Exception {
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSiz e()));
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
ImageIO.write(image, "bmp", outputStream);
return outputStream.toByteArray();
}
}


}


FileUploader :


package com.sample.network.nio;


import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;


/**
* @author avb
*/
public class FileUploader {


public static boolean upload(InetSocketAddress address, byte[] bytes) throws Exception {
try (SocketChannel socketChannel = SocketChannel.open()) {
if (socketChannel.connect(address)) {
ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
buffer.clear();
buffer.put(bytes);
buffer.flip();
socketChannel.write(buffer);
return true;
}
}
return false;
}


}


FileDownloader :


package com.sample.network.nio;


import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
* @author avb
*/
public class FileDownloader implements Runnable, AutoCloseable {


private final ServerSocketChannel serverSocketChannel;
private final ExecutorService service = Executors.newCachedThreadPool();
private final String downloadLocation;
private boolean running;


public FileDownloader(int port, String downloadLocation) throws IOException {
serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(port));
Path path = Paths.get(downloadLocation);
this.downloadLocation = path.toString();
if (Files.notExists(path)) {
Files.createDirectories(path);
}
running = true;
}


public void stop() {
running = false;
}


@Override
public void run() {
while (running) {
try {
service.submit(new Downloader(serverSocketChannel.accept()));
} catch (IOException ignored) {
}
}
}


private class Downloader implements Runnable {


private final SocketChannel socketChannel;


private Downloader(SocketChannel socketChannel) {
this.socketChannel = socketChannel;
}


@Override
public void run() {
ByteBuffer buffer = ByteBuffer.allocate(64 * 1024);
int read;
try (FileOutputStream fileOutputStream = new FileOutputStream(downloadLocation + "/" + UUID.randomUUID() + ".bmp")) {
while (true) {
read = socketChannel.read(buffer);
if (read == -1) {
break;
}
buffer.flip();
fileOutputStream.write(buffer.array(), 0, read);
buffer.clear();
}
System.out.println("Downloaded!!!!!!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socketChannel.close();
} catch (IOException ignored) {
}
}
}


}


@Override
public void close() throws Exception {
running = false;
service.shutdown();
serverSocketChannel.close();
}


}


تست :


package test;


import com.sample.network.nio.FileDownloader;
import com.sample.network.nio.FileUploader;
import com.sample.util.ScreenUtil;


import java.net.InetSocketAddress;


/**
* @author avb
*/
public class Main {


public static void main(String[] args) throws Exception {
FileDownloader downloader = new FileDownloader(14141, "D:/downloads/screen_shots");
new Thread(downloader).start();
for (int i = 0; i < 10; i++) {
if (FileUploader.upload(new InetSocketAddress("localhost", 14141), ScreenUtil.takeScreenShot())) {
System.out.println("Uploaded!!!!!!");
Thread.sleep(1000);
} else {
System.out.println("failed!!!!!!");
}
}
downloader.close();
}


}

staaaaaar
دوشنبه 29 دی 1393, 21:48 عصر
خیلی ممنون از راهنمایی کامل و جامعتون

بخش های سورس رو جدا توضیح بدین ک چیکار میکنن و...

staaaaaar
دوشنبه 29 دی 1393, 21:50 عصر
میخواستم بدونم این سورس مدام عکس میگیره و به صفحه نمایش سرور میفرسته؟
سوال دیگه هم اینه ک دوتا pc باید با چه وسیله ای به هم وصل بشن؟

این کد رو من قبلا نوشتم ک بطور مداوم از صفحه نمایش عکس میگیره
آیا درسته؟ و میشه ازش تواین برنامه استفاده کرد؟
package poroject2;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import javax.imageio.ImageIO;


public class p2 {

public static void main(String[] args) {
try {
for(int i=0;i<20;i++){
Rectangle a=new Rectangle(Toolkit.getDefaultToolkit().getScreenSiz e());
Robot tmp1 = null;
tmp1 = new Robot();
BufferedImage n=tmp1.createScreenCapture(a);
ImageIO.write(n, "jpg",new File("D:\\Programming\\poroject\\2\\image\\"+System.nanoTime()+".jpg"));
Thread.sleep(1000);
}
}
catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}



}

}

ahmad.mo74
سه شنبه 30 دی 1393, 12:33 عصر
سلام ممنون

کدی که خودتون نوشتین درسته، هر ثانیه یه اسکرین شات میگیره و ذخیره میکنه.

کلاس FileUploader برای اینه که عکس رو از کلاینت به سرور بفرستید. آدرس سرور و فایل ([]byte) رو به متد میدید و اونم میفرسته به سرور.

کلاس FileDownloader حکم سرور رو داره و روی پورتی که بهش گفتیم listen میکنه و منتظر میمونه تا بهش سوکت زده شه. وقتی سوکت رو گرفت اون رو میفرسته تو یه ترد جدا تا فایل رو بگیره از سوکت و خودش دوباره تو همون حلقه while منتظر سوکت بعدی میمونه.
توی کلاس درونی Downloader در محلی که گفتیم عکس ها ذخیره بشه یه فایل میسازه با یه اسم unique تا فایل ها هم نام نشن و شروع میکنه به خوندن byte ها از سوکت تا زمانی که به انتها نرسیده و توی فایل write میکنه.

میتونید FileDownloader و FileUploader رو روی دوتا کامیپوتر جدا ران کنید بعد ip و پورتی که سرور روش ران شده رو بدید به FileUploader و فایل بفرستید.

staaaaaar
سه شنبه 30 دی 1393, 20:19 عصر
خب سوال اینجاست چطوری ip رو بدم میشه کدش رو واسه دوتا کامپیوتر تغییر بدین؟ ممنون میشم
و اینکه با چ وسیله ای دو کامپیوتر به هم وصل میشن؟ پورت شبکه ؟ وای فای ؟ یا ....

ahmad.mo74
چهارشنبه 01 بهمن 1393, 12:23 عصر
فرض کنیم الان میخواید بین دوتا کامپیوتر عکس بفرستید.
فعلا چون ip valid ندارید فقط میتونید از طریق شبکه لوکال وصل بشید. مثلا اگر ip کامپبوتر سرور 192.168.1.30 باشه :

اول سرورو روی یه کامپیوتر اجرا کن :


import com.sample.network.nio.FileDownloader;


/**
* @author avb
*/
public class Server {


public static void main(String[] args) throws Exception {
FileDownloader downloader = new FileDownloader(14141, "D:/downloads/screen_shots");
new Thread(downloader).start();
System.out.println("Press Enter to Stop Server!!!");
System.in.read();
downloader.close();
System.exit(0);
}


}


و بعد روی کامپیوتر دیگه :


import com.sample.network.nio.FileUploader;
import com.sample.util.ScreenUtil;


import java.net.InetSocketAddress;


/**
* @author avb
*/
public class Client {


public static void main(String[] args) throws Exception {
System.out.println("Press Enter to Send a Screen Shot!!!");
while (true) {
System.in.read();
if (FileUploader.upload(new InetSocketAddress("192.168.1.30", 14141), ScreenUtil.takeScreenShot())) {
System.out.println("Uploaded!!!!!!");
} else {
System.out.println("failed!!!!!!");
}
}
}


}

staaaaaar
دوشنبه 06 بهمن 1393, 11:43 صبح
سلام ممنون

کدی که خودتون نوشتین درسته، هر ثانیه یه اسکرین شات میگیره و ذخیره میکنه.

کلاس FileUploader برای اینه که عکس رو از کلاینت به سرور بفرستید. آدرس سرور و فایل ([]byte) رو به متد میدید و اونم میفرسته به سرور.

کلاس FileDownloader حکم سرور رو داره و روی پورتی که بهش گفتیم listen میکنه و منتظر میمونه تا بهش سوکت زده شه. وقتی سوکت رو گرفت اون رو میفرسته تو یه ترد جدا تا فایل رو بگیره از سوکت و خودش دوباره تو همون حلقه while منتظر سوکت بعدی میمونه.
توی کلاس درونی Downloader در محلی که گفتیم عکس ها ذخیره بشه یه فایل میسازه با یه اسم unique تا فایل ها هم نام نشن و شروع میکنه به خوندن byte ها از سوکت تا زمانی که به انتها نرسیده و توی فایل write میکنه.

میتونید FileDownloader و FileUploader رو روی دوتا کامیپوتر جدا ران کنید بعد ip و پورتی که سرور روش ران شده رو بدید به FileUploader و فایل بفرستید.

سلام دوباره
ببخشید اینکه گفتید آدرس سرور و فایل رو به متد میدیم منظور همین این("D:/downloads/screen_shots") که تو کلاس تست هست یا جور دیگه باید این کارو بکنم چون من بدون
دست زدن به کد ها اونارو اجرا کردم ولی عکسی تو صفحه نمایش نشون نداد!

staaaaaar
سه شنبه 07 بهمن 1393, 18:41 عصر
؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟ ؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟ ؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟؟

ahmad.mo74
چهارشنبه 08 بهمن 1393, 11:47 صبح
سلام. کلاینت شما باید به ip و پورت سرور رو داشته باشه تا بتونه بهش سوکت بزنه.

به سرور هم باید مسیری که میخوایم فایل ها ذخیره بشه رو بدیم مثلا D:/downloads و وقتی فایلی فرستاده شد توی اون فولدر ذخیرش کنه.