Java“SyncServer”允许两个用户同时编辑字符串变量

时间:2016-01-30 13:59:54

标签: java

我在查找问题原因时遇到了一些麻烦。

程序的功能如下...... Server允许多个用户登录(连接到服务器)并使用任一开始命令编辑名为text的相同字符串变量{ {1}}(用于替换整个字符串)或rep:(附加到字符串)。

当客户端连接时,他们必须输入命令。无论命令是什么,它都会在同一个窗口中回显给它们(在不同的CMD窗口中同时运行服务器和客户端)。因此,如果他们输入app:,则回音将为hello

如果输入的命令是ECHO: hello,则服务器中的rep:tight字符串变量应更改为包含text,然后应返回/显示在客户端cmd窗口中{ {1}} - 没有ECHO。

如果之后的命令是tight,则服务器中的tight字符串变量应更改为包含app:rope,并应返回/显示在客户端cmd窗口中{ {1}}。

此外,用户不能输入4个字符以下的任何值,因此SynchClient应显示错误消息并提示用户输入其他值。

我遇到的问题是每次新输入后我的回显值都没有改变。我得到了第一个输入命令的返回,就是这样,我正在努力让我全神贯注。

编辑:如果你自己运行该程序,可能是最好的。

以下是我的SynchServer.java文件:

text

和我的SynchClient.java文件:

tightrope

编辑2: 我的工作解决方案:

服务器:

tightrope

客户端:

import java.io.*;
import java.net.*;
import java.util.*;

public class SynchServer
{

    public static void main(String[] args) throws IOException
    {
        ServerSocket serverSocket = null;
        final int PORT = 1234;
        Socket client;
        ClientHandler handler;

        try
        {
            serverSocket = new ServerSocket(PORT);
        }
        catch (IOException ioEx)
        {
            System.out.println("\nUnable to set up port!");
            System.exit(1);
        }

        System.out.println("\nServer running...\n");

        do
        {
            //Wait for client.
            client = serverSocket.accept();

            System.out.println("\nNew client accepted.\n");
            handler = new ClientHandler(client);
            handler.start();
        }while (true);
    }
}

class ClientHandler extends Thread
{
    private Socket client;
    private Scanner input;
    private PrintWriter output;

    private static String text = "";

    public ClientHandler(Socket socket) throws IOException
    {
        client = socket;

        input = new Scanner(client.getInputStream());
        output = new PrintWriter(client.getOutputStream(),true);
    }

    public void run()
    {
        String head, tail, received;

        received = input.nextLine();
        head = received.substring(0, 4);
        tail = received.substring(4);

        while (!received.equals("QUIT"))
        {
            if (head.equals("rep:"))
                changeText(tail);

            else
                if (head.equals("app:"))
                    appendText(tail);

            output.println(text);
            output.println("ECHO: " + received);
        }

        try
        {
            System.out.println("Closing down connection...");
            client.close();
        }
        catch(IOException ioEx)
        {
            System.out.println("* Disconnection problem! *");
        }
    }

    private synchronized void changeText(String changedText)
    {
        text = changedText;
    }

    private synchronized void appendText(String appendedText)
    {
        text += appendedText;
    }
}

2 个答案:

答案 0 :(得分:5)

这主要与static字段无关。你的错误就在这个循环中:

       while (!received.equals("QUIT")) {
            if (head.equals("rep:"))
                changeText(tail);

            else if (head.equals("app:"))
                appendText(tail);

            output.println(text);
            output.println("ECHO: " + received);
        }

它在第一次客户端输入后无限运行,并且每次都不从输入流中读取新值。

这些行:

        received = input.nextLine();
        head = received.substring(0, 4);
        tail = received.substring(4);

应该放入循环中:

    while (!received.equals("QUIT")) {
        received = input.nextLine();
        head = received.substring(0, 4);
        tail = received.substring(4);
        ...

<强>更新

确切地说,它有另一个次要问题,这两行:

            output.println(text);
            output.println("ECHO: " + received);

他们应该改为:

        output.println("ECHO: " + text);

(否则你发送两条不同的线路。)

答案 1 :(得分:2)

您有一个同步块,它分别应用于每个对象,而不是每个对象,因为synchronized块适用于不是整个类的对象。

您可以使用静态锁,以便所有客户等待轮到他们。检查此链接以查看静态锁定和非静态锁定之间的比较

Static versus non-static lock object in synchronized block

和这个

How to lock a method for a whole class using synchronized?

因此,您应该从static字段声明中删除text修饰符:

private String text = "";

在这种情况下,synchronizedchangeText方法根本不需要appendText