socket : 使用定时器获取二进制图像
我正在尝试通过客户端从服务器获取多个图像。
我的最终目标是通过套接字(在同一台计算机上)从Java程序中的C++程序和Ogre生成的电影中获取图像,因为JNI对我来说似乎非常困难。
为了尝试一下,我在java下做了一个客户端/服务器,只是为了测试,但效果不佳。事实上,结果是相当随机的,我有时会得到 2 个、有时 4 个图像,但从来不会得到全部。
我认为我的流没有很好地同步,我也想知道 UDP 是否不能更合适,但我不知道该怎么做。
这是我使用的代码:
public class Client {
static final int port = 3334;
static final String host = "aluminod";
public static final double STEP = 2000.0;
public static final int DELAY = 0;
private Socket socket;
private PrintWriter printWriter;
private BufferedReader input;
private int imgNumber = 0;
private static MoviePanel pane;
private Timer timer;
public Client() throws UnknownHostException, IOException{
this.socket = new Socket(host, port);
System.out.println("SOCKET = " + socket);
this.printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
this.input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
start();
}
public static void main(String[] args){
JFrame frame = new JFrame("test");
pane = new MoviePanel();
frame.setPreferredSize(new Dimension(600,400));
frame.setSize(new Dimension(600,400));
frame.setVisible(true);
frame.setLocation(Toolkit.getDefaultToolkit().getScreenSize().width/2-300, Toolkit.getDefaultToolkit().getScreenSize().height/2-200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(pane, BorderLayout.CENTER);
frame.add(pane);
try {
new Client();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void start(){
this.timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
try {
sendParamsToVC();
} catch (IOException e) {
e.printStackTrace();
}
}
}, DELAY, (long) STEP);
}
private void sendParamsToVC() throws IOException {
System.out.println("---sending---");
String mess = buildMessage();
//envoi du message au serveur
printWriter.println(mess);
// lecture de la réponse du serveur
InputStream is = socket.getInputStream();
int taille = Integer.parseInt(input.readLine());
byte[] mybytearray = new byte[taille];
is.read(mybytearray, 0, taille);
BufferedImage img = ImageIO.read(new ByteArrayInputStream(mybytearray));
pane.change(img);
imgNumber++;
}
private String buildMessage(){
String mess;
if(imgNumber <10)mess = "000"+imgNumber;
else if(imgNumber<=13)mess = "00"+imgNumber;
else {
mess = "NO_IMG";
timer.cancel();
}
return mess;
}
}
public class Server {
static final int port = 3334;
public static void main(String[] args) throws Exception {
ServerSocket servsocket = new ServerSocket(port);
while (true) {
Socket client = servsocket.accept();
System.out.println("connection accepted");
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedOutputStream output = new BufferedOutputStream(client.getOutputStream());
while (true) {
String str = reader.readLine(); // lecture du message
if (str.equals("NO_IMG")){
System.out.println("ECHO = " + str);
System.out.println("fermeture");
break;
}
System.out.println("ECHO = " + str); // trace locale
//renvoi de l'image
OutputStream os = client.getOutputStream();
byte[]data = getByteFromImage(str);
PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
writer.println(data.length);
writer.flush();
os.write(data, 0, data.length);
os.flush();
}
output.close();
reader.close();
client.close();
}
}
public static byte[] getByteFromImage(String numImage) {
BufferedImage img = ImageLoader.createBufferedImage(numImage);
/** On crée la nouvelle image */
BufferedImage bufferedImage = new BufferedImage(
img.getWidth(null),
img.getHeight(null),
BufferedImage.TYPE_INT_BGR );
Graphics g = bufferedImage.createGraphics();
g.drawImage(img,0,0,null);
g.dispose();
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ImageIO.write(bufferedImage, "jpeg", out);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
byte buffer[] = out.toByteArray();
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
return (buffer);
}
}
I'm trying to get multiple images from a server with a client.
My ultimate goal is to get images from a movie generated by a C++ program with Ogre in a Java program by sockets (on the same computer), because JNI seems very difficult to me.
To try it, i made a client/server both under java, just for test, but it doesn't work well. In fact, the result is pretty random and i get sometimes 2, sometimes 4 images, but never all.
I think my streams are not well synchronized, and i was wondering too if UDP couldn't be more appropriated, but i don't know how to do it.
Here are the codes i use :
public class Client {
static final int port = 3334;
static final String host = "aluminod";
public static final double STEP = 2000.0;
public static final int DELAY = 0;
private Socket socket;
private PrintWriter printWriter;
private BufferedReader input;
private int imgNumber = 0;
private static MoviePanel pane;
private Timer timer;
public Client() throws UnknownHostException, IOException{
this.socket = new Socket(host, port);
System.out.println("SOCKET = " + socket);
this.printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())),true);
this.input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
start();
}
public static void main(String[] args){
JFrame frame = new JFrame("test");
pane = new MoviePanel();
frame.setPreferredSize(new Dimension(600,400));
frame.setSize(new Dimension(600,400));
frame.setVisible(true);
frame.setLocation(Toolkit.getDefaultToolkit().getScreenSize().width/2-300, Toolkit.getDefaultToolkit().getScreenSize().height/2-200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(pane, BorderLayout.CENTER);
frame.add(pane);
try {
new Client();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void start(){
this.timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
try {
sendParamsToVC();
} catch (IOException e) {
e.printStackTrace();
}
}
}, DELAY, (long) STEP);
}
private void sendParamsToVC() throws IOException {
System.out.println("---sending---");
String mess = buildMessage();
//envoi du message au serveur
printWriter.println(mess);
// lecture de la réponse du serveur
InputStream is = socket.getInputStream();
int taille = Integer.parseInt(input.readLine());
byte[] mybytearray = new byte[taille];
is.read(mybytearray, 0, taille);
BufferedImage img = ImageIO.read(new ByteArrayInputStream(mybytearray));
pane.change(img);
imgNumber++;
}
private String buildMessage(){
String mess;
if(imgNumber <10)mess = "000"+imgNumber;
else if(imgNumber<=13)mess = "00"+imgNumber;
else {
mess = "NO_IMG";
timer.cancel();
}
return mess;
}
}
public class Server {
static final int port = 3334;
public static void main(String[] args) throws Exception {
ServerSocket servsocket = new ServerSocket(port);
while (true) {
Socket client = servsocket.accept();
System.out.println("connection accepted");
BufferedReader reader = new BufferedReader(new InputStreamReader(client.getInputStream()));
BufferedOutputStream output = new BufferedOutputStream(client.getOutputStream());
while (true) {
String str = reader.readLine(); // lecture du message
if (str.equals("NO_IMG")){
System.out.println("ECHO = " + str);
System.out.println("fermeture");
break;
}
System.out.println("ECHO = " + str); // trace locale
//renvoi de l'image
OutputStream os = client.getOutputStream();
byte[]data = getByteFromImage(str);
PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(client.getOutputStream())),true);
writer.println(data.length);
writer.flush();
os.write(data, 0, data.length);
os.flush();
}
output.close();
reader.close();
client.close();
}
}
public static byte[] getByteFromImage(String numImage) {
BufferedImage img = ImageLoader.createBufferedImage(numImage);
/** On crée la nouvelle image */
BufferedImage bufferedImage = new BufferedImage(
img.getWidth(null),
img.getHeight(null),
BufferedImage.TYPE_INT_BGR );
Graphics g = bufferedImage.createGraphics();
g.drawImage(img,0,0,null);
g.dispose();
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ImageIO.write(bufferedImage, "jpeg", out);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
byte buffer[] = out.toByteArray();
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
return (buffer);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
读取器/写入器流用于字符数据。不要将它们用于二进制数据。使用(缓冲)InputStream/OutputStream
编辑:忘记我上面所说的。我检查了您的其余代码,看起来您正在混合流,并且客户端在发送命令时不会刷新流。这意味着可以在客户端进行缓冲。
Edit2:另一个错误是您没有检查 read 返回的内容。它返回一个 int 值,表示您已收到多少字节。这并不总是与您的缓冲区大小相同。它可以更少。你需要处理这个问题。
The reader/writer streams are for character data. Don't use them for binary data. Use (Buffered)InputStream/OutputStream
Edit: Forget what I said above. I checked the rest of your code, and it looks like you are mixing streams, and the client isn't flushing the stream when it sends commands. The means that is can be buffered on the client.
Edit2: Another error is that you don't check what read returns. It returns an int that says home many bytes you have received. That isn't always the same as your buffer size. It can be less. You need to handle that.