我正在创建一个Swing白板应用程序,其中有一个输入设备和一个输出设备。使用输入设备的人可以在屏幕上绘画,然后该屏幕会显示在输出设备上(以及输入设备上)。
[绘图/绘画在输入设备(即客户端)上工作良好,但是我无法将坐标正确发送到服务器(输出设备)。
第一个问题是服务器中的BufferedReader无法立即接收数据。即使我在输入设备上绘图,服务器也会在30秒后绘制线条。
第二个问题是,即使客户端正在发送坐标,服务器也无法接收所有坐标,因此行不完整/断开。
编辑:我实现了一个计数器,我发现服务器仅收到客户端绘制的一半直线的坐标对,从而导致图像不完整。此外,它以替代方式接收它们。 (即,如果客户端发送第1行,第2行,第3行,第4行的坐标,则服务器仅接收第1行和第3行(这就是为什么显示不完整图像的原因)。
这是我在mouseDragged ActionListener中拥有的代码。
g2.drawLine(oldX, oldY, currentX, currentY);
sendData();
public void sendData() {
// I am using a PrintWriter as the 'out'
out.println(oldX + " " + oldY + " " + currentX + " " + currentY);
}
这里是服务器中接收数据的代码
while (true) {
if (in.readLine() != null) {
String message = in.readLine();
System.out.println(i + ": " + message);
drawOnImage(message);
i++;
}
}
文件中的完整代码如下。
客户端
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import javax.swing.JComponent;
public class DrawArea extends JComponent {
// Image in which we're going to draw
private Image image;
// Graphics2D object ==> used to draw on
private Graphics2D g2;
// Mouse coordinates
private int currentX, currentY, oldX, oldY;
Socket socket;
BufferedReader in;
PrintWriter out;
public DrawArea() throws IOException {
setDoubleBuffered(false);
socket = new Socket("localhost", 7777); // connecting to correct port.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream());
System.out.println("Connected");
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// save coord x,y when mouse is pressed
oldX = e.getX();
oldY = e.getY();
}
});
ArrayList<String> coords = new ArrayList();
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
// coord x,y when drag mouse
currentX = e.getX();
currentY = e.getY();
if (g2 != null) {
// draw line if g2 context not null
g2.drawLine(oldX, oldY, currentX, currentY);
sendData();
coords.add(oldX + "," + oldY + " " + currentX + "," + currentY);
System.out.println(coords.size());
System.out.println(oldX + "," + oldY + " " + currentX + "," + currentY);
// refresh draw area to repaint
repaint();
// store current coords x,y as olds x,y
oldX = currentX;
oldY = currentY;
}
}
});
}
public void sendData() {
out.println(oldX + " " + oldY + " " + currentX + " " + currentY);
}
@Override
protected void paintComponent(Graphics g) {
if (image == null) {
// image to draw null ==> we create
image = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) image.getGraphics();
// enable antialiasing
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// clear draw area
clear();
}
g.drawImage(image, 0, 0, null);
}
public void clear() {
g2.setPaint(Color.white);
// draw white on entire draw area to clear
g2.fillRect(0, 0, getSize().width, getSize().height);
g2.setPaint(Color.black);
repaint();
}
服务器端
import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Server implements Runnable {
static ServerSocket serverSocket;
static Socket socket;
BufferedReader in; // reading. receiving data.
TestDraw drawOutput; // this is the canvas on which the lines are drawn
public Server(TestDraw drawOutput) {
this.drawOutput = drawOutput;
}
@Override
public void run() {
try {
System.out.println("Running");
serverSocket = new ServerSocket(7777);
socket = serverSocket.accept();
System.out.println("A Client Connected");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
draw = false;
int i = 1;
while (true) {
if (in.readLine() != null) {
String message = in.readLine();
System.out.println(i + ": " + message);
drawOnImage(message);
i++;
}
}
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
void drawOnImage(String message) {
String[] splitted = message.split(" ");
int pointOneX = Integer.parseInt(splitted[0]);
int pointOneY = Integer.parseInt(splitted[1]);
int pointTwoX = Integer.parseInt(splitted[2]);
int pointTwoY = Integer.parseInt(splitted[3]);
drawOutput.g2.drawLine(pointOneX,pointOneY,pointTwoX,pointTwoY);
drawOutput.repaint();
}
}
PrintWriter
,并且网络套接字在内部缓冲区中累积数据。需要“清除”缓冲区以确保尽快发送数据。
一种构造方法是在构造PrintWriter时设置“ autoflush”属性。这样可以确保每次调用println
时都会刷新缓冲区。
out = new PrintWriter(socket.getOutputStream(), true);
另一种方法是在您认为需要时自己调用冲洗,例如:
out.println(oldX + " " + oldY + " " + currentX + " " + currentY);
out.flush();
关于接收方的问题,这是因为两次调用readLine
。每个调用都读取一个新行,并且您基本上是在丢弃第一行。
更改
if (in.readLine() != null) {
String message = in.readLine();
to
String message = in.readLine();
if (message != null) {