Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向多个客户发布过帐_Java_Sockets_Hashmap - Fatal编程技术网

Java 向多个客户发布过帐

Java 向多个客户发布过帐,java,sockets,hashmap,Java,Sockets,Hashmap,嘿,伙计们,我最近刚开始使用套接字,但在向多个客户发布时遇到了一个问题。我使用多线程来处理这个问题,我试图在hashmap中保存服务器需要发送的所有客户端数据,但是在循环并添加到hashmap时。它似乎只增加了一个人。这是密码 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.ObjectInputStream; import ja

嘿,伙计们,我最近刚开始使用套接字,但在向多个客户发布时遇到了一个问题。我使用多线程来处理这个问题,我试图在hashmap中保存服务器需要发送的所有客户端数据,但是在循环并添加到hashmap时。它似乎只增加了一个人。这是密码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

public class HostMain extends Thread {

/**
 * The set of all names of clients in the chat room.  Maintained
 * so that we can check that new clients are not registering name
 * already in use.
 */
private static HashMap<String, ConnectedUsers> users = new HashMap<String, ConnectedUsers>();

public HostMain() throws IOException
{

}

public void run()
{
    try
    {
    System.err.println("SERVER:The chat server is running.");
    ServerSocket listener = new ServerSocket(PORT);
    System.err.println("SERVER:socket created");
    Constants.getInstance().getStatusLabel().setText("Server is running. Join when ready");
    try {
        while (true) {

            System.err.println("SERVER:New handler being created");
            new Handler(listener.accept()).start();

        }
    } finally {
        listener.close();
    }
    }
    catch(Exception e)
    {
        Constants.getInstance().getStatusLabel().setText("SERVER:A HOST IS ALREADY RUNNING ON THIS PORT!");
        System.err.println("SERVER:A HOST IS ALREADY RUNNING ON THIS PORT!");
    }
}
/**
 * The port that the server listens on.
 */
private static final int PORT = 1337;




/**
 * The appplication main method, which just listens on a port and
 * spawns handler threads.
 */

/**
 * A handler thread class.  Handlers are spawned from the listening
 * loop and are responsible for a dealing with a single client
 * and broadcasting its messages.
 */
private static class Handler extends Thread {
    private String name;
    private Socket socket;
    private BufferedReader in;
    private PrintWriter out;
    private ObjectInputStream oin;
    private ObjectOutputStream oout;
    /**
     * Constructs a handler thread, squirreling away the socket.
     * All the interesting work is done in the run method.
     */
    public Handler(Socket socket) {
        this.socket = socket;
    }

    /**
     * Services this thread's client by repeatedly requesting a
     * screen name until a unique one has been submitted, then
     * acknowledges the name and registers the output stream for
     * the client in a global set, then repeatedly gets inputs and
     * broadcasts them.
     */
    public void run() {
        try {

            // Create object streams for the socket.
            in = new BufferedReader(new InputStreamReader(
                socket.getInputStream()));
            out = new PrintWriter(socket.getOutputStream(), true);
            oin = new ObjectInputStream(socket.getInputStream());
            oout = new ObjectOutputStream(socket.getOutputStream());


            //add socket to a list
            users.put(name,new ConnectedUsers(name,oout));
            System.err.println(users.size());
            // Accept messages from this client and broadcast them.
            // Ignore other clients that cannot be broadcasted to.
            while (true) {

                Object obj = oin.readObject();
                Messages message = (Messages)obj;
                if(obj.getClass().equals(Messages.class))
                {
                    for(Map.Entry<String, ConnectedUsers> entry:users.entrySet())
                    {

                            ConnectedUsers user = entry.getValue(); 
                            user.objectWriter.writeObject(message);
                    }

                }            

            }
        } catch (IOException | ClassNotFoundException e) {
            System.out.println(e);
        } finally {
            // This client is going down!  Remove its name and its print
            // writer from the sets, and close its socket.
            if (name != null) {
                users.remove(name);
            }
            try {
                socket.close();
            } catch (IOException e) {
            }
        }
    }
}
}
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.InputStreamReader;
导入java.io.ObjectInputStream;
导入java.io.ObjectOutputStream;
导入java.io.PrintWriter;
导入java.net.ServerSocket;
导入java.net.Socket;
导入java.util.HashMap;
导入java.util.HashSet;
导入java.util.Iterator;
导入java.util.Map;
公共类HostMain扩展线程{
/**
*聊天室中所有客户端名称的集合。已维护
*这样我们就可以检查新客户端是否未注册名称
*已经在使用中。
*/
private static HashMap users=new HashMap();
public HostMain()引发IOException
{
}
公开募捐
{
尝试
{
System.err.println(“服务器:聊天服务器正在运行。”);
ServerSocket侦听器=新的ServerSocket(端口);
System.err.println(“服务器:已创建套接字”);
常量.getInstance().getStatusLabel().setText(“服务器正在运行,准备好后加入”);
试一试{
while(true){
System.err.println(“服务器:正在创建新的处理程序”);
新处理程序(listener.accept()).start();
}
}最后{
listener.close();
}
}
捕获(例外e)
{
常量.getInstance().getStatusLabel().setText(“服务器:此端口上已运行主机!”);
System.err.println(“服务器:此端口上已运行主机!”);
}
}
/**
*服务器侦听的端口。
*/
专用静态最终int端口=1337;
/**
*AppApplication main方法,它只侦听端口和
*生成处理程序线程。
*/
/**
*处理程序线程类。处理程序是从侦听线程派生的
*循环并负责与单个客户机进行交易
*并广播其信息。
*/
私有静态类处理程序扩展线程{
私有字符串名称;
专用插座;
中的私有缓冲区读取器;
私人打印输出;
私有对象输出流;
私有对象输出流输出;
/**
*构造一个处理程序线程,存储套接字。
*所有有趣的工作都是在run方法中完成的。
*/
公共处理程序(套接字){
this.socket=socket;
}
/**
*通过重复请求
*屏幕名称,直到提交了唯一的屏幕名称,然后
*确认该名称并为其注册输出流
*客户端在一个全局集合中,然后重复获取输入和
*广播他们。
*/
公开募捐{
试一试{
//为套接字创建对象流。
in=新的BufferedReader(新的InputStreamReader(
getInputStream());
out=新的PrintWriter(socket.getOutputStream(),true);
oin=newObjectInputStream(socket.getInputStream());
oout=newObjectOutputStream(socket.getOutputStream());
//将套接字添加到列表中
put(name,newconnectedUsers(name,oout));
System.err.println(users.size());
//接受来自此客户端的消息并广播它们。
//忽略无法广播到的其他客户端。
while(true){
Object obj=oin.readObject();
消息消息=(消息)对象;
if(obj.getClass().equals(Messages.class))
{
for(Map.Entry:users.entrySet())
{
ConnectedUsers user=entry.getValue();
user.objectWriter.writeObject(消息);
}
}            
}
}捕获(IOException | ClassNotFoundException e){
系统输出打印ln(e);
}最后{
//此客户端正在关闭!请删除其名称和打印内容
//从集合中选择writer,然后关闭其套接字。
if(name!=null){
用户。删除(名称);
}
试一试{
socket.close();
}捕获(IOE异常){
}
}
}
}
}

name
似乎总是空的,所以您一直使用同一个键(空),这可以解释为什么地图中只有一个用户

还要注意,HashMap不是线程安全的——除非在从线程访问映射时添加某种形式的同步,否则它可能会产生令人惊讶的结果


您可以改为使用线程安全映射,例如ConcurrentHashMap。

我明白您所说的这些优异结果的含义。谢谢你的帮助!