Java(网络):passing incremented values between client and server

标签 java sockets

我应该有多个客户端连接到本地主机,并且在连接客户端后,他可以按添加按钮将值增加 1。例如,有 2 个客户端(A 和 B)。 A点击添加按钮,值(ctr)增加1(ctr=1),如果B点击添加按钮,值(ctr)再次增加1(ctr)(ctr =2)

但我正在努力为一个客户获取正确的结果,因此我将坚持首先解决为一个客户获取正确的结果,然后再继续从多个客户获取正确的结果。但我确实希望任何人都可以在多个客户端方面为我提供帮助。

我不太擅长网络,并尝试实现这一点,这里是我的逻辑一个客户端

-在我的按钮actionListener中,每次按下“添加”按钮时,我都会将消息“add”从客户端发送到服务器。

-服务器收到消息“add”,会将“ctr”变量加1;

-服务器将递增的 ctr 传递给客户端。

但是在我点击“添加”按钮 3 次后,我从代码中得到的输出相当奇怪且不稳定。

我的输出

Starting SomeProcess  
1500476704 <--Incremented value passed back to client from the server, it should return 1
SomeProcess took 4 ms
Starting SomeProcess
1751217765 <--Incremented value passed back to client from the server, it should return 2
SomeProcess took 0 ms
Starting SomeProcess
543387502 <--Incremented value passed back to client from the server, it should return 3
SomeProcess took 0 ms

我的代码

客户端.java

import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class Client extends JPanel {
    private JButton addBtn = new JButton("Add");
    private long start = 0;
    private PrintWriter output = null;
    private BufferedReader input = null;
    private Socket socket;

    public Client() {
        setLayout(new FlowLayout());
        add(addBtn);

        try {
            socket = new Socket("localhost",4444);
            output = new PrintWriter(socket.getOutputStream(), true);
            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));

        }catch (IOException exception) {
            System.out.println("Error: " + exception);
        }

        addBtn.addActionListener(new AddBtnListener());
    }

    public class AddBtnListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            Thread t = new Thread(new Runnable() {
                public void run() {

                    System.out.println("Starting SomeProcess");
                    start = System.currentTimeMillis();
                    output.println("add");

                    try {
                        DataInputStream inputInt = new DataInputStream((socket.getInputStream()));    
                        System.out.println(inputInt.readInt());
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    long duration = System.currentTimeMillis() - start;
                    System.out.printf("SomeProcess took %,d ms%n", duration );
                }
            });
            t.start();
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new Client());
                frame.pack();
                frame.getPreferredSize();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);
            }
        });
    }
}

服务器.java

import java.awt.EventQueue;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.JPanel; 
import javax.swing.JTextArea;

@SuppressWarnings("serial")
public class Server extends JPanel {

    private Socket threadSocket;
    private JTextArea textArea = new JTextArea(30,30);

    public Server() {
        add(textArea);
        textArea.setEditable(false);
        Thread t = new Thread(new acceptClient());
        t.start();
    }

    class acceptClient implements Runnable {

        @Override   
        public void run() {
            try {
                ServerSocket sSocket = new ServerSocket(4444);
                textArea.append("Server started at: " + new Date());
                while(true) {
                    Socket socket = sSocket.accept();
                    ClientThread cT = new ClientThread(socket);
                    new Thread(cT).start();

                } 
            } catch(IOException exception) {
                System.out.println("Error: " + exception);
            }
        }
    }

    class ClientThread extends Thread {
        String temp = " ";
        DataOutputStream outputInt = null;
        int ctr = 0;
        PrintWriter output;

        public ClientThread(Socket socket) {
            threadSocket = socket;
        }

        @Override  
        public void run() { 
            while(true) {
                try {
                    output = new PrintWriter(threadSocket.getOutputStream(), true);
                    BufferedReader input = new BufferedReader(new InputStreamReader(threadSocket.getInputStream()));
                    output.println("You have connected at: " + new Date());
                    textArea.append("\nClient connected\n");
                    temp = input.readLine();

                    if(temp.equals("add")) {
                        synchronized(this) {
                            ctr++;
                            textArea.append(Integer.toString(ctr));
                            outputInt.write(ctr);
                        }
                    }

                } catch(IOException exception) {
                    System.out.println("Error: " + exception);
                }
            }
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new Server());
                frame.setLocationRelativeTo(null);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
                frame.setResizable(false);
            }
        });
    }
}

最佳答案

看看你的写/读过程...

首先,您的服务器...

output = new PrintWriter(threadSocket.getOutputStream(), true);
output.println("You have connected at: " + new Date());
//...
ctr++;
outputInt.write(ctr);

但是你的客户只会...

DataInputStream inputInt = new DataInputStream((socket.getInputStream()));
System.out.println(inputInt.readInt());

...这意味着您实际读取的是来自服务器的“您已连接于:” + new Date() 响应。

您需要确保您阅读内容的顺序与编写内容的顺序相同...

我可能会考虑做的是简化流程...我会简单地继续使用您已经设置的 PrintWriter,而不是引入 DataOutputStream简单地做一些事情,比如...

ctr++;
textArea.append(Integer.toString(ctr));
output.println(ctr);

在服务器内......

在客户端,您可以这样做

System.out.println(input.readLine());
System.out.println(input.readLine());

它将读取“连接”消息和计数器...

旁注

关于您的服务器ClientThread,有一些事情让我担心......

  1. 无需在while-loop内重新创建PrintWriterBufferedReader,事实上,output 并不需要是类实例变量...
  2. 如果由于某种原因引发 Exceptionrun 方法将永远不会退出,这意味着您可能会陷入永无休止的循环
  3. 我',不确定您是否真的需要 synchronized block ,因为 ctr 是此线程上下文中的实例字段,因此除非某些内容要尝试并更改它在外部,这只是额外的开销...但我暂时不理会它...

相反,我可能会想做一些类似的事情......

try (PrintWriter output = new PrintWriter(threadSocket.getOutputStream(), true)) {
    try (BufferedReader input = new BufferedReader(new InputStreamReader(threadSocket.getInputStream()))) {

        while (true) {
            output.println("You have connected at: " + new Date());
            textArea.append("\nClient connected\n");
            temp = input.readLine();

            if (temp != null) {

                if (temp.equals("add")) {
                    synchronized (this) {
                        ctr++;
                        textArea.append(Integer.toString(ctr));
                        output.println(ctr);
                    }
                }

            }

        }

    }
} catch (IOException exp) {
    exp.printStackTrace();
}

相反。

虽然我知道您可以使用单个 try-with-resource 语句,但为了清楚起见,我想将两个流创建分开......

关于Java(网络):passing incremented values between client and server,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25478695/

相关文章:

node.js - 当我在服务器上部署时不断收到 "socket.io/?EIO=3&transport=polling&t=Lvm1SGO"404 错误

java - 我的应用程序在横向 View 中困惑

java - 如何在 System.exit(0) 之前打印一行到终端?同步问题

c# - 多个客户端的异步 TCP 服务器

c - 本地 linux 套接字接收旧数据

Java Socket - read() 方法如何知道是否已到达流的末尾?

Java迷宫打破封闭

java - 用jboss调用soap不起作用

java - 如何通过selenium检查伪元素是否存在

java - Java 套接字中的并行处理无法正常工作