Java-向所有客户端发送消息
我正在使用套接字服务器和线程创建聊天服务器。在我的服务器ChatServer.java、ThreadedServer.java和Main.java中有3个类。我的客户端有2个ChatClient.java,Main.java。我需要这样做,当消息从客户端发送到服务器时,服务器会将消息发送到所有客户端 ChatServer.javaJava-向所有客户端发送消息,java,Java,我正在使用套接字服务器和线程创建聊天服务器。在我的服务器ChatServer.java、ThreadedServer.java和Main.java中有3个类。我的客户端有2个ChatClient.java,Main.java。我需要这样做,当消息从客户端发送到服务器时,服务器会将消息发送到所有客户端 ChatServer.java package server; import java.io.*; import java.net.*; public class ChatServer {
package server;
import java.io.*;
import java.net.*;
public class ChatServer {
protected Socket s;
protected Socket ss;
public ChatServer() {
try {
ServerSocket ss=new ServerSocket(6969);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void main(String []args) throws IOException {
ss.close();
}
});
while (true) {
Socket s =ss.accept();
new ThreadedServer(s).start();
}
}catch(Exception e) {
System.out.println(e);
}
new ThreadedServer(s).start();
}
}
package server;
import java.io.*;
import java.net.*;
public class ThreadedServer extends Thread{
protected Socket socket;
public ThreadedServer(Socket clientSocket) {
this.socket = clientSocket;
}
public void run() {
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
while (true) {
String str=(String)dis.readUTF();
String remote = socket.getInetAddress().toString();
String newmes = remote + ": " + str;
dos.writeUTF(newmes);
System.out.println(newmes);
if (str.toUpperCase() == "QUIT") {
socket.close();
break;
}else if (str.toUpperCase() == "EXIT") {
socket.close();
break;
}
}
}catch(Exception e) {
System.out.println(e);
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
/**
* A multithreaded chat room server. When a client connects the
* server requests a screen name by sending the client the
* text "SUBMITNAME", and keeps requesting a name until
* a unique one is received. After a client submits a unique
* name, the server acknowledges with "NAMEACCEPTED". Then
* all messages from that client will be broadcast to all other
* clients that have submitted a unique screen name. The
* broadcast messages are prefixed with "MESSAGE ".
*
* Because this is just a teaching example to illustrate a simple
* chat server, there are a few features that have been left out.
* Two are very useful and belong in production code:
*
* 1. The protocol should be enhanced so that the client can
* send clean disconnect messages to the server.
*
* 2. The server should do some logging.
*/
public class ChatServer {
/**
* The port that the server listens on.
*/
private static final int PORT = 9001;
/**
* 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 HashSet<String> names = new HashSet<String>();
/**
* The set of all the print writers for all the clients. This
* set is kept so we can easily broadcast messages.
*/
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
/**
* The appplication main method, which just listens on a port and
* spawns handler threads.
*/
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
/**
* 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;
/**
* 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 character streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Request a name from this client. Keep requesting until
// a name is submitted that is not already used. Note that
// checking for the existence of a name and adding the name
// must be done while locking the set of names.
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
// Now that a successful name has been chosen, add the
// socket's print writer to the set of all writers so
// this client can receive broadcast messages.
out.println("NAMEACCEPTED");
writers.add(out);
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException 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) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
ThreadedServer.java
package server;
import java.io.*;
import java.net.*;
public class ChatServer {
protected Socket s;
protected Socket ss;
public ChatServer() {
try {
ServerSocket ss=new ServerSocket(6969);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void main(String []args) throws IOException {
ss.close();
}
});
while (true) {
Socket s =ss.accept();
new ThreadedServer(s).start();
}
}catch(Exception e) {
System.out.println(e);
}
new ThreadedServer(s).start();
}
}
package server;
import java.io.*;
import java.net.*;
public class ThreadedServer extends Thread{
protected Socket socket;
public ThreadedServer(Socket clientSocket) {
this.socket = clientSocket;
}
public void run() {
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
while (true) {
String str=(String)dis.readUTF();
String remote = socket.getInetAddress().toString();
String newmes = remote + ": " + str;
dos.writeUTF(newmes);
System.out.println(newmes);
if (str.toUpperCase() == "QUIT") {
socket.close();
break;
}else if (str.toUpperCase() == "EXIT") {
socket.close();
break;
}
}
}catch(Exception e) {
System.out.println(e);
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
/**
* A multithreaded chat room server. When a client connects the
* server requests a screen name by sending the client the
* text "SUBMITNAME", and keeps requesting a name until
* a unique one is received. After a client submits a unique
* name, the server acknowledges with "NAMEACCEPTED". Then
* all messages from that client will be broadcast to all other
* clients that have submitted a unique screen name. The
* broadcast messages are prefixed with "MESSAGE ".
*
* Because this is just a teaching example to illustrate a simple
* chat server, there are a few features that have been left out.
* Two are very useful and belong in production code:
*
* 1. The protocol should be enhanced so that the client can
* send clean disconnect messages to the server.
*
* 2. The server should do some logging.
*/
public class ChatServer {
/**
* The port that the server listens on.
*/
private static final int PORT = 9001;
/**
* 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 HashSet<String> names = new HashSet<String>();
/**
* The set of all the print writers for all the clients. This
* set is kept so we can easily broadcast messages.
*/
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
/**
* The appplication main method, which just listens on a port and
* spawns handler threads.
*/
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
/**
* 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;
/**
* 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 character streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Request a name from this client. Keep requesting until
// a name is submitted that is not already used. Note that
// checking for the existence of a name and adding the name
// must be done while locking the set of names.
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
// Now that a successful name has been chosen, add the
// socket's print writer to the set of all writers so
// this client can receive broadcast messages.
out.println("NAMEACCEPTED");
writers.add(out);
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException 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) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
Main.java(服务器)
包服务器
public class Main {
public static void main(String[] args) {
ChatServer chat = new ChatServer();
}
}
下面是Client.java的
ChatClient.java
包客户端
import java.io.*;
import java.net.*;
public class ChatClient {
public ChatClient() {
try {
Socket s = new Socket("10.4.27.29",6969);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void main(String []args) throws IOException {
s.close();
}
});
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
DataInputStream dis = new DataInputStream(s.getInputStream());
while (true) {
String message = System.console().readLine();
dos.writeUTF(message);
System.out.println(dis.readUTF());
}
}catch(Exception e) {
System.out.println(e);
}
}
}
Main.java(客户端)
求求你,任何帮助都会令人惊讶的
此外,如果有任何想法能让这更美好,我们将不胜感激。谢谢 试着运行这个。这是我做的一个有效的 ChatServer.java
package server;
import java.io.*;
import java.net.*;
public class ChatServer {
protected Socket s;
protected Socket ss;
public ChatServer() {
try {
ServerSocket ss=new ServerSocket(6969);
Runtime.getRuntime().addShutdownHook(new Thread() {
public void main(String []args) throws IOException {
ss.close();
}
});
while (true) {
Socket s =ss.accept();
new ThreadedServer(s).start();
}
}catch(Exception e) {
System.out.println(e);
}
new ThreadedServer(s).start();
}
}
package server;
import java.io.*;
import java.net.*;
public class ThreadedServer extends Thread{
protected Socket socket;
public ThreadedServer(Socket clientSocket) {
this.socket = clientSocket;
}
public void run() {
try {
DataInputStream dis = new DataInputStream(socket.getInputStream());
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
while (true) {
String str=(String)dis.readUTF();
String remote = socket.getInetAddress().toString();
String newmes = remote + ": " + str;
dos.writeUTF(newmes);
System.out.println(newmes);
if (str.toUpperCase() == "QUIT") {
socket.close();
break;
}else if (str.toUpperCase() == "EXIT") {
socket.close();
break;
}
}
}catch(Exception e) {
System.out.println(e);
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
/**
* A multithreaded chat room server. When a client connects the
* server requests a screen name by sending the client the
* text "SUBMITNAME", and keeps requesting a name until
* a unique one is received. After a client submits a unique
* name, the server acknowledges with "NAMEACCEPTED". Then
* all messages from that client will be broadcast to all other
* clients that have submitted a unique screen name. The
* broadcast messages are prefixed with "MESSAGE ".
*
* Because this is just a teaching example to illustrate a simple
* chat server, there are a few features that have been left out.
* Two are very useful and belong in production code:
*
* 1. The protocol should be enhanced so that the client can
* send clean disconnect messages to the server.
*
* 2. The server should do some logging.
*/
public class ChatServer {
/**
* The port that the server listens on.
*/
private static final int PORT = 9001;
/**
* 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 HashSet<String> names = new HashSet<String>();
/**
* The set of all the print writers for all the clients. This
* set is kept so we can easily broadcast messages.
*/
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
/**
* The appplication main method, which just listens on a port and
* spawns handler threads.
*/
public static void main(String[] args) throws Exception {
System.out.println("The chat server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
/**
* 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;
/**
* 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 character streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Request a name from this client. Keep requesting until
// a name is submitted that is not already used. Note that
// checking for the existence of a name and adding the name
// must be done while locking the set of names.
while (true) {
out.println("SUBMITNAME");
name = in.readLine();
if (name == null) {
return;
}
synchronized (names) {
if (!names.contains(name)) {
names.add(name);
break;
}
}
}
// Now that a successful name has been chosen, add the
// socket's print writer to the set of all writers so
// this client can receive broadcast messages.
out.println("NAMEACCEPTED");
writers.add(out);
// Accept messages from this client and broadcast them.
// Ignore other clients that cannot be broadcasted to.
while (true) {
String input = in.readLine();
if (input == null) {
return;
}
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
}
}
} catch (IOException 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) {
names.remove(name);
}
if (out != null) {
writers.remove(out);
}
try {
socket.close();
} catch (IOException e) {
}
}
}
}
}
关于“让这更美好”。考虑使用非阻塞套接字IO。关于将消息发送到所有客户端:在服务器上保留一组套接字,并将消息发送到每个已连接的套接字(但从发送的套接字除外)。我正在寻找将其添加到代码中的方法。这听起来可能有些刺耳,但我希望它能与我的代码一起工作,因为我试图从头开始构建,但无法理解这个概念。那么看看我的示例,然后实现与您类似的逻辑。您不需要使用我的全部代码,但是有一个您想要的“工作示例”会有所帮助。我在我的客户机上使用JavaSwing,但这并不意味着您必须这样做。