【问题标题】:Trying to do a broadcast server that echos clients尝试做一个回显客户端的广播服务器
【发布时间】:2018-06-30 14:42:52
【问题描述】:

我正在尝试进行一个简单的群聊,其中有一个服务器和多个客户端。 目标是当客户端向服务器发送消息时,服务器只是将该消息发送回所有其他客户端。我让服务器发送一条由他编写的消息发送给所有客户端,但他没有发送客户端消息。

服务器代码:

package Group;
import java.net.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.*;

public class GroupServer extends Thread {
    private ServerSocket server;
    protected List<ClientHandler> clients;

    public static void main(String[] args) throws IOException {
        new GroupServer(9876);
    }

    public GroupServer(int port) {
        try {
            this.server = new ServerSocket(port);
            System.out.println("New server initialized!");
            clients = Collections.synchronizedList(new ArrayList<ClientHandler>());
            this.start();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public void run() {
    while (true) {
        try {
            Socket client = server.accept();
            System.out.println(client.getInetAddress().getHostName() + " connected");
            ClientHandler newClient = new ClientHandler(client);
            clients.add(newClient);
            new SendMessage(clients);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
}

class ClientHandler {
protected Socket client;
protected PrintWriter out;
protected DataInputStream in;

public ClientHandler(Socket client) {
    this.client = client;
    try {
        this.out = new PrintWriter(client.getOutputStream());
        this.in = new DataInputStream(client.getInputStream());

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

class SendMessage extends Thread {
    protected List<ClientHandler> clients;
    protected String userInput;
    protected String sendMessage;
    protected BufferedReader stdIn;
    protected DataInputStream in;

    public SendMessage(List<ClientHandler> clients) {
        this.clients = clients;
        this.userInput = null;
        this.start();
    }

    public void run() {
        System.out.println("New Communication Thread Started");
        if (clients.size() == 1) {
            System.out.println("Enter message:");
        }
        try {
            if (clients.size() > 0) {
                this.stdIn = new BufferedReader(new InputStreamReader(System.in));

                while ((this.userInput = stdIn.readLine()) != null) {
                    if (userInput != null & userInput.length() > 0) {
                        for (ClientHandler client : clients) {
                            sendMessage = client.in.readUTF();
                            client.out.println(sendMessage);
                            client.out.flush();
                        Thread.currentThread();
                        Thread.sleep(1 * 1000);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

客户端代码:

package Group;
import java.net.*;
import java.io.*;
import java.util.logging.*;

public class GroupClient {
protected Socket client;
protected BufferedReader in;

public static void main(String[] args) {
    new GroupClient("Localhost", 9876);
}

public GroupClient(String hostName, int ip) {
    try {
        this.client = new Socket(hostName, ip);
        this.in = new BufferedReader(new InputStreamReader(
                this.client.getInputStream()));
        String buffer = null;
        while ((buffer = in.readLine()) != null) {
            System.out.println(buffer);
        }
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}       
}

我认为错误出在服务器中,更准确地说是在 SendMessage 类上。 感谢您的关注。

【问题讨论】:

  • 为什么每次有客户端连接时都创建一个新的SendMessage?此外,如果服务器只应该传播客户端消息,为什么接收用户输入的代码在服务器端(SendMessage 内部)而不是客户端运行?
  • 如果您仍然遇到问题,您可以轻松地从我的网络框架中受益:github.com/jhg023/SimpleNet

标签: java sockets server


【解决方案1】:

所有客户端只有一个线程“SendMessage”。

第一次在循环中调用client.in.readUTF() 时,线程会阻塞,直到客户端发送了一些东西。因为所有其他客户端都由同一个线程处理。也都被屏蔽了。

您要么每个客户端套接字有一个线程,要么采用 nio 选择器方式(首选)。

同时修复@jingx 提到的问题。

对于同步数组列表,使用 CopyOnWriteArrayList。它专门用于这类用例。同步有助于并发添加和删除,但不适用于并发迭代。 CopyOnWriteArrayList 解决了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    • 2016-05-24
    • 2015-06-19
    • 1970-01-01
    • 2016-02-24
    • 2018-11-14
    相关资源
    最近更新 更多