Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.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_Multithreading_Sockets_Data Structures - Fatal编程技术网

Java 多线程服务器

Java 多线程服务器,java,multithreading,sockets,data-structures,Java,Multithreading,Sockets,Data Structures,我不认为我完全理解让多个客户端连接到一台服务器的概念。 我见过很多不同的方法,听过很多不同的方法 据我所知,每次ServerSocket从客户端套接字获得连接时,它都会创建一个新的套接字,以便继续侦听 当我看到人们用代码(服务器端)编写它时,他们总是使用一个套接字。 从那以后我一直这样做,但仍然没有取得进展 我的朋友编写了客户端,它与服务器一起工作,但是我们在让服务器全局显示消息方面遇到了问题。这就是我的结构(前3个用于服务器,最后一个用于客户端: Server.java package Mai

我不认为我完全理解让多个客户端连接到一台服务器的概念。 我见过很多不同的方法,听过很多不同的方法

据我所知,每次ServerSocket从客户端套接字获得连接时,它都会创建一个新的套接字,以便继续侦听

当我看到人们用代码(服务器端)编写它时,他们总是使用一个套接字。 从那以后我一直这样做,但仍然没有取得进展

我的朋友编写了客户端,它与服务器一起工作,但是我们在让服务器全局显示消息方面遇到了问题。这就是我的结构(前3个用于服务器,最后一个用于客户端:

Server.java

package Main;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import Streams.Stream;

public class Server {

    public static final int maxConnections = 10;

    ServerSocket serverSocket;
    Socket socket;

    User[] users = new User[maxConnections];

    public Server() {
        try {
            serverSocket = new ServerSocket(43594);

            while(Stream.streams < maxConnections) {
                socket = serverSocket.accept();

                for(User user : users) {
                    if(user == null) {
                        user = new User(socket);

                        Thread t = new Thread(user);
                        t.start();
                        System.out.println("Someone has joined the chat!");
                        return;
                    }
                }

            }


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

    public static void main(String[] args) {
        new Server();
    }
}
Stream.java

package Streams;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class Stream {
    public static int streams = 0;

    Socket socket;

    ObjectInputStream input; ObjectOutputStream output;
    Object data;

    public Stream(Socket userSocket) {
        streams++;
        socket = userSocket;

        try{
            input = new ObjectInputStream(userSocket.getInputStream());
            output = new ObjectOutputStream(userSocket.getOutputStream());
        }catch(IOException e) { e.printStackTrace(); }

    }

    public void sendData(Object data) throws IOException {
        output.writeObject(data);
        output.flush();
    }

    public Object recieveData() throws IOException, ClassNotFoundException {
        return data = input.readObject();
    }


    public boolean exists() {
        if(socket.isClosed()) return false; else return true;
    }

}
Client.java

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Client extends JFrame {

    private JTextField userText;
    private JTextArea chatWindow;
    private ObjectOutputStream out;
    private ObjectInputStream in;
    private String message = "";
    private String serverIP;
    private Socket clientSocket;
    private int port = 43594;
    Boolean CNC = false;

    //constructor
    public Client(String serverIP) {
        super("Client Chat");

        this.serverIP = serverIP;

        userText = new JTextField();
        userText.setEditable(false);
        userText.addActionListener(new ActionListener(){
                public void actionPerformed(ActionEvent e) {
                    if(userText.getText().length() > 0) {
                        sendMessageToServer(userText.getText());
                        userText.setText("");
                    }
                }
            }
        );
        add(new ClientMenu(), BorderLayout.NORTH);
        add(userText, BorderLayout.SOUTH);
        chatWindow = new JTextArea();
        chatWindow.setEditable(false);
        add(new JScrollPane(chatWindow), BorderLayout.CENTER);
        add(new JScrollPane(new ClientTable()), BorderLayout.EAST);
        setSize(600, 300);
        setVisible(true);
    }

    //connect to server
    public void startRunning() {
        try{
            connectToServer();
            setupStreams();
            whileChatting();
        } catch(EOFException eofException) {
            showMessage("\n Client terminated the connetion");
        }catch(IOException ioException) {
            ioException.printStackTrace();
        }finally{
            closeCrap();
        }
    }

    //connect to server
    private void connectToServer() {
        showMessage("Attempting to connect to server... \n");
        try {
            clientSocket = new Socket(serverIP, port);
        } catch (UnknownHostException e) {
            CNC = true;
            e.printStackTrace();
        } catch (IOException e) {
            CNC = true;
            e.printStackTrace();
        }
        //showMessage("Connected to:" + connection.getInetAddress().getHostName());
    }

    //setup streams to send and receive messages
    private void setupStreams() {
        try {
            out = new ObjectOutputStream(clientSocket.getOutputStream());
            out.flush();
            in = new ObjectInputStream(clientSocket.getInputStream());
            showMessage("Stream established! \n");
            showMessage("Use ::setname to change your name \n");
        }catch(IOException e) { e.printStackTrace(); }

    }

    //while chatting with server
    private void whileChatting() throws IOException{
        ableToType(true);
        do{
            try{
                message = (String) in.readObject();

                showMessage("\n" + message);
            }catch(ClassNotFoundException classNotfoundException) {
                showMessage("\n ERROR! Message cannot be read");
            }
        }while(!message.equals("SERVER - END"));
    }

    //close the streams and sockets
    private void closeCrap(){
        if(CNC) {
            showMessage("ERROR! Could not connect to server");
        } else {
        showMessage("\n Ending connections...");
        ableToType(false);
        try{
            out.close();
            in.close();
            clientSocket.close();
        }catch(IOException ioException) {
            ioException.printStackTrace();
        }
      }
    }

    private void sendMessageToServer(String message) {
        try{
            out.writeObject(message);
            out.flush();
        }catch(IOException ioException) {
            chatWindow.append("\n ERROR! Could not send message!");
        }
    }

    //change/update chatWindow
    private void showMessage(final String message) {
        SwingUtilities.invokeLater(
                new Runnable() {
                    public void run() {
                        chatWindow.append(message);
                    }
                }
            );
    }

    //gives user permission to enter messages into text box
    private void ableToType(final boolean tof) {
        SwingUtilities.invokeLater(
                new Runnable() {
                    public void run() {
                        userText.setEditable(tof);
                    }
                }
            );
    }

    public static void main(String[] args) {
        Client c = new Client("thisisatestip.zapto.org");
        c.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        c.setLocationRelativeTo(null);
        c.startRunning();
    }
}
我在想,与其让ServerSocket是静态的,不如像这样调用用户的构造函数

User(new Socket())
并接受用户类中的连接。
请让我知道

让我先说一句,我已经很久没有使用Java了,但我只是用C#编写了一个简单的客户机/服务器聊天程序。希望所有的概念都是一样的

关于您的服务器类,我注意到以下几点:

  • 您可以从构造函数中“返回”。不确定这在Java中是否合法(或是一个好主意),但从外观上看,它会在客户端连接后立即关闭服务器。例如:客户端建立连接,服务器分配“用户”对于数组,服务器从构造函数返回,主退出,程序终止。我建议让构造函数设置所有内容,然后使用“start”方法无限循环并添加新客户端。在本机代码(C/C++)中,“accept()”块-我不确定Java中是否存在这种情况,但您可以在这里利用它发挥自己的优势。鉴于此,您还可以使用动态大小的数组(我想是ArrayList?),这样您就不限于10个客户端。因此,获取连接,使用套接字创建用户对象,让该用户自己做,循环并等待另一个客户端连接

  • 您可以为每个用户对象创建一个线程。这可能不是一个好主意,因为拥有一堆并发线程所带来的开销将大大降低服务器的性能。我在聊天实现中所做的是在服务器上创建一个线程,用于接收来自客户端的数据,并在每次客户端出现时创建一个工作线程我在服务器端使用了回调函数(不确定Java中是否有类似的回调函数)和非阻塞操作,这样我就不必为每个客户机设置专用线程

  • 如果您使用的是线程,那么您将需要绕过重要数据。通过防止两个(或多个)线程同时尝试访问资源来锁定对资源的序列化访问


  • 至于您最初的问题,我建议如下:接受服务器端的连接,从服务器端获取为客户端创建的套接字,并将其传递给用户对象。

    是的,我正在阅读线程池,我将进一步研究它。对于您的#1,我从for循环返回,因此它将只创建一个用户,因为条件是ECK为null,它们都以null开头。感谢您提供的关于锁定的信息,我从来都不知道。当您说获取已创建的套接字时,您的意思是创建一个套接字实例,每次我使用serverSocket.accept()时,它将创建另一个套接字?我刚刚意识到,我想我需要放一些书签来显示从何处返回。类似于UserLoop:…编辑:我必须中断,而不是返回FacePalm是的,中断比返回更有意义!当我说“获取已创建的套接字”时,我指的是来自serverSocket.accept()的返回值.accept调用会在您的serverSocket上尝试挂起客户端连接。与serverSocket关联的原始套接字保持打开状态,准备接受更多连接。您使用返回的套接字对象与客户端通信。我仍然不能100%确定套接字。我知道serverSocket会将连接发送到新的Socket以便它可以继续侦听,但我是否需要为我获得的每个连接创建一个新的套接字实例?还是将serverSocket.accept();自动为我创建?抱歉,我迟到了几天!调用
    serverSocket.accept())
    将在返回时返回一个新创建的客户端套接字实例。因此,是的,它将自动为您创建对象。但是,为了让您真正与客户端进行通信,您需要在服务器类中存储一个套接字对象,以便您以后可以访问它。如果您愿意,我可以在我的回答中添加一个简短的示例,以便请确保我们意见一致。
    User(new Socket())