为什么我的服务器(使用BufferedReader)没有接收到客户端发送的所有数据?

问题描述 投票:1回答:1

我正在创建一个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();

    }
}

java swing paint
1个回答
0
投票

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) { 
© www.soinside.com 2019 - 2024. All rights reserved.