简单的java聊天服务器,只向其他客户端而不是发送者广播
我一直在学习一个简单java聊天服务器的教程,希望对其进行修改,使其不会回显到原始发件人。我试着用我有限的技能来改造它,但我知道没有任何效果,任何帮助都将被感激简单的java聊天服务器,只向其他客户端而不是发送者广播,java,Java,我一直在学习一个简单java聊天服务器的教程,希望对其进行修改,使其不会回显到原始发件人。我试着用我有限的技能来改造它,但我知道没有任何效果,任何帮助都将被感激 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.So
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;
public class ChatServer {
// Port that the server listens on.
private static final int PORT = 9001;
// Creates names
private static HashSet<String> names = new HashSet<String>();
// Creates writers
private static HashSet<PrintWriter> writers = new HashSet<PrintWriter>();
// Main method, which just listens on a port and spawns handler threads.
public static void main(String[] args) throws Exception {
System.out.println("The Chatty server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
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;
}
// Where to add the section that prevents sending to original sender?
for (PrintWriter writer : writers) {
writer.println("MESSAGE " + name + ": " + input);
System.out.println(writer);
System.out.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) {
}
}
}
}
}
公共类聊天服务器{
//服务器侦听的端口。
专用静态最终int端口=9001;
//创建名称
私有静态HashSet name=新HashSet();
//创造作家
私有静态HashMap writers=newhashmap();
//Main方法,它只侦听端口并生成处理程序线程。
公共静态void main(字符串[]args)引发异常{
System.out.println(“聊天服务器正在运行”);
ServerSocket侦听器=新的ServerSocket(端口);
试一试{
while(true){
新处理程序(listener.accept()).start();
}
}最后{
listener.close();
}
}
私有静态类处理程序扩展线程{
私有字符串名称;
专用插座;
中的私有缓冲区读取器;
私人打印输出;
公共处理程序(套接字){
this.socket=socket;
}
公开募捐{
试一试{
//为套接字创建字符流。
in=新的BufferedReader(新的InputStreamReader(
getInputStream());
out=新的PrintWriter(socket.getOutputStream(),true);
字符串keyForEachUser=socket.getInetAddress().toString();
//从该客户端请求名称。继续请求,直到
//提交的名称尚未使用。请注意
//检查名称是否存在并添加名称
//必须在锁定名称集时执行。
while(true){
out.println(“提交名称”);
name=in.readLine();
if(name==null){
返回;
}
已同步(名称){
如果(!names.contains(name)){
名称。添加(名称);
打破
}
}
}
//现在已经选择了一个成功的名称,添加
//socket的打印写入程序到所有写入程序的集合,因此
//此客户端可以接收广播消息。
out.println(“接受名称”);
writers.put(keyForEachUser,out);
//接受来自此客户端的消息并广播它们。
//忽略无法广播到的其他客户端。
while(true){
字符串输入=in.readLine();
如果(输入==null){
返回;
}
//在何处添加阻止发送到原始发件人的部分?
for(字符串键:writers.keySet()){
if(key.equalsIgnoreCase(keyForEachUser)){
//原始用户未发送数据
}否则{
PrintWriter=writers.get(key);//获取正确的输出流
writer.println(“消息“+name+”:“+input”);
System.out.println(writer);
System.out.println(“消息”+name+:“+input”);
}
}
}
}捕获(IOE异常){
系统输出打印ln(e);
}最后{
//此客户端正在关闭!请删除其名称和打印内容
//从集合中选择writer,然后关闭其套接字。
if(name!=null){
姓名。删除(姓名);
}
if(out!=null){
删除(出);
}
试一试{
socket.close();
}捕获(IOE异常){
}
}
}
}
}
我对您的程序做了一些更改,您以前的代码的问题是您无法识别连接的用户。现在,我用一个hashmap对象来存储PrintWriter,我在hashmap中使用的键是users inetaddress,这在pc之间是唯一的。也许你应该试试这个{
//服务器侦听的端口。
专用静态最终int端口=9001;
//创建名称
私有静态HashSet name=新HashSet();
//创造作家
私有静态HashMap writers=newhashmap();
//Main方法,它只侦听端口并生成处理程序线程。
公共静态void main(字符串[]args)引发异常{
System.out.println(“聊天服务器正在运行”);
ServerSocket侦听器=新的ServerSocket(端口);
试一试{
while(true){
新处理程序(listener.accept()).start();
}
}最后{
listener.close();
}
}
私有静态类处理程序扩展线程{
私有字符串名称;
专用插座;
中的私有缓冲区读取器;
私人打印输出;
公共处理程序(套接字){
this.socket=socket;
}
公开募捐{
试一试{
//为套接字创建字符流。
in=新的BufferedReader(新的InputStreamReader(
getInputStream());
out=新的PrintWriter(socket.getOutputStream(),true);
字符串keyForEachUser=socket.getInetAddress().toString();
//从该客户端请求名称。继续请求,直到
//提交的名称尚未使用。请注意
//检查名称是否存在并添加名称
//必须在锁定名称集时执行。
while(true){
out.println(“提交名称”);
name=in.readLine();
if(name==null){
返回;
}
已同步(名称){
如果(!names.contains(name)){
名称。添加(名称);
打破
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class ChatClient {
BufferedReader in;
PrintWriter out;
JFrame frame = new JFrame("Chatty");
JTextField textField = new JTextField(40);
JTextArea messageArea = new JTextArea(8, 40);
public ChatClient() {
// Layout GUI
textField.setEditable(false);
messageArea.setEditable(false);
frame.getContentPane().add(textField, "North");
frame.getContentPane().add(new JScrollPane(messageArea), "Center");
frame.pack();
// Add Listeners
textField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
out.println(textField.getText());
textField.setText("");
}
});
}
// Prompt for and return the desired screen name.
private String getName() {
return JOptionPane.showInputDialog(
frame,
"Choose a screen name:",
"Screen name selection",
JOptionPane.PLAIN_MESSAGE);
}
// Connects to the server then enters the processing loop.
private void run() throws IOException {
// Make connection and initialize streams
String serverAddress = "0";
Socket socket = new Socket(serverAddress, 9001);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Process all messages from server, according to the protocol.
while (true) {
String line = in.readLine();
if (line.startsWith("SUBMITNAME")) {
out.println(getName());
} else if (line.startsWith("NAMEACCEPTED")) {
textField.setEditable(true);
} else if (line.startsWith("MESSAGE")) {
messageArea.append(line.substring(8) + "\n");
}
}
}
// Runs the client as an application with a closeable frame.
public static void main(String[] args) throws Exception {
ChatClient client = new ChatClient();
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setVisible(true);
client.run();
}
}
public class ChatServer {
// Port that the server listens on.
private static final int PORT = 9001;
// Creates names
private static HashSet<String> names = new HashSet<String>();
// Creates writers
private static HashMap<String,PrintWriter> writers = new HashMap<String,PrintWriter>();
// Main method, which just listens on a port and spawns handler threads.
public static void main(String[] args) throws Exception {
System.out.println("The Chatty server is running.");
ServerSocket listener = new ServerSocket(PORT);
try {
while (true) {
new Handler(listener.accept()).start();
}
} finally {
listener.close();
}
}
private static class Handler extends Thread {
private String name;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
public Handler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
// Create character streams for the socket.
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
String keyForEachUser = socket.getInetAddress().toString();
// 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.put(keyForEachUser,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;
}
// Where to add the section that prevents sending to original sender?
for (String key : writers.keySet()) {
if (key.equalsIgnoreCase(keyForEachUser)) {
//original user founf not sending the data
}else{
PrintWriter writer = writers.get(key); //getting the correct output stream
writer.println("MESSAGE " + name + ": " + input);
System.out.println(writer);
System.out.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) {
}
}
}
}
}