Java 服务器在用户之间交替,而不是广播
我一直在开发一个消息系统,其中用户键入服务器IP/端口,然后该服务器接收消息并将其转发给服务器上的所有其他用户。整个程序基于我从头重写的echo服务器,它为每个服务器创建两个线程,一个用于接收消息,另一个用于发送消息。这两个线程由DatagramPacket系统连接,因此如果服务器从一个套接字接收到消息,它会将消息发送回所有其他用户,因为他们的线程正在侦听相同的内容,这就是我遇到问题的地方;除了接收消息的用户根据登录时间进行切换之外,其他一切都正常工作 连接两个客户端时的问题示例: 客户端1发送10条消息:Java 服务器在用户之间交替,而不是广播,java,multithreading,sockets,datagram,Java,Multithreading,Sockets,Datagram,我一直在开发一个消息系统,其中用户键入服务器IP/端口,然后该服务器接收消息并将其转发给服务器上的所有其他用户。整个程序基于我从头重写的echo服务器,它为每个服务器创建两个线程,一个用于接收消息,另一个用于发送消息。这两个线程由DatagramPacket系统连接,因此如果服务器从一个套接字接收到消息,它会将消息发送回所有其他用户,因为他们的线程正在侦听相同的内容,这就是我遇到问题的地方;除了接收消息的用户根据登录时间进行切换之外,其他一切都正常工作 连接两个客户端时的问题示例: 客户端1发送
0
1
2
3
4
5
6
7
8
9
服务器将接收所有这些数据
客户1收到:
1
3
5
7
9
0
2
4
6
8
客户2收到:
1
3
5
7
9
0
2
4
6
8
以下是客户端的代码:
import java.io.*;
import java.util.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MessageClient {
public static void main(String[] args) {
System.out.println("Starting Message System...");
Scanner in = new Scanner(System.in);
MessageClient mc = new MessageClient();
String input;
System.out.println(":System Started, type help for help.");
System.out.print(":");
while (true) {
input = in.nextLine();
if (input.equalsIgnoreCase("HELP")) {
mc.printHelp();
System.out.print(":");
} else if (input.equalsIgnoreCase("QUIT")) {
System.exit(0);
} else if (input.equalsIgnoreCase("CONNECT")) {
mc.connect(in);
in.nextLine();
System.out.print(":");
} else {
System.out.print("No command found.\n:");
}
}
}
public static void printHelp() {
System.out.println("help\tShow this prompt\nconnect\tStarts a new connection\nquit\tQuit the program\nexit\tExit a connection");
}
public void connect(Scanner in) {
Socket soc = null;
InetAddress addr = null;
System.out.print("IP_ADDRESS/HOST:");
String ip = in.nextLine();
System.out.print("PORT:");
int port = in.nextInt();
try {
System.out.println("Attempting to connect to HOST:\'" + ip + "\' on PORT:\'" + port + "\'");
addr = InetAddress.getByName(ip);
soc = new Socket(addr, port);
} catch(Exception e) {
System.out.println("Error connecting to server: " + e.getLocalizedMessage());
return;
}
SwingUtilities.invokeLater(new MessageGUI(ip + ":" + port, soc));
}
}
class MessageGUI implements Runnable {
public MessageGUI(String windowName, Socket server) {
JFrame window = new JFrame(windowName);
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.setSize(500, 300);
window.setLayout(new BorderLayout());
window.setVisible(true);
MessageReceive mr = new MessageReceive(server);
mr.setEditable(false);
mr.setBackground(new Color(0, 0, 0));
mr.setForeground(new Color(0, 255, 0));
mr.setVisible(true);
new Thread(mr).start();
window.add(mr, BorderLayout.CENTER);
DataOutputStream dos = null;
try {
dos = new DataOutputStream(server.getOutputStream());
} catch(Exception e) {
System.out.println("Error creating output stream to server: " + e.getLocalizedMessage());
}
JTextField input = new JTextField();
input.addActionListener(new MessageSend(server, input, dos));
input.setBackground(new Color(0, 0, 0));
input.setForeground(new Color(0, 255, 0));
window.add(input, BorderLayout.PAGE_END);
System.out.println("Displaying connection.");
}
public void run() {}
}
class MessageReceive extends JTextArea implements Runnable {
protected Socket server;
public MessageReceive(Socket server) {
this.server = server;
}
public void run() {
DataInputStream dis = null;
int bytes;
try {
dis = new DataInputStream(server.getInputStream());
} catch(Exception e) {
System.out.println("Error connecting server: " + e.getLocalizedMessage());
}
this.append("Connected.\n");
while (true) {
try {
while ((bytes = dis.read()) != -1) this.append(String.valueOf((char) bytes));
} catch(Exception e) {
System.out.println("Error reading from server: " + e.getLocalizedMessage());
return;
}
}
}
}
class MessageSend implements ActionListener {
protected Socket server;
protected JTextField input;
protected DataOutputStream dos = null;
public MessageSend(Socket server, JTextField input, DataOutputStream dos) {
this.server = server;
this.input = input;
this.dos = dos;
}
public void actionPerformed(ActionEvent ae) {
try {
dos.writeBytes(input.getText() + "\n");
input.setText("");
} catch(Exception e) {
System.out.println("Error writing to server output stream: " + e.getLocalizedMessage());
}
}
}
以下是服务器的代码:
import java.io.*;
import java.net.*;
import java.util.*;
public class MessageServer {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
MessageServer ms = new MessageServer();
System.out.println("Starting server on port " + port + "...");
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
} catch(Exception e) {
System.out.println("Error creating server: " + e.getLocalizedMessage());
System.exit(0);
}
System.out.println("Created server port, now waiting for users...");
Socket client = null;
DatagramSocket ds = null;
try {
ds = new DatagramSocket(4);
} catch(Exception e) {
System.out.println("IN:Error creating Datagram Server: " + e.getLocalizedMessage());
e.printStackTrace();
System.exit(0);
}
while (true) {
try {
client = ss.accept();
System.out.println("Connecting user: " + client.getInetAddress().toString());
} catch(Exception e) {
System.out.println("Error on server: " + e.getLocalizedMessage());
}
new MessageConnectionIn(client, ds).start();
new MessageConnectionOut(client, ds).start();
}
}
}
class MessageConnectionOut extends Thread {
protected Socket client;
public DatagramSocket ds;
public MessageConnectionOut(Socket client, DatagramSocket ds) {
this.client = client;
this.ds = ds;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":OUT");
try {
System.out.println("OUT:User connected.");
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
while (true) {
byte[] outgoing = new byte[4096];
DatagramPacket dp = new DatagramPacket(outgoing, outgoing.length);
ds.receive(dp);
dos.writeChars(new String(outgoing) + "\n");
}
} catch(Exception e) {
System.out.println("OUT:Error connecting " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
class MessageConnectionIn extends Thread {
protected Socket client;
public DatagramSocket ds;
public MessageConnectionIn(Socket client, DatagramSocket ds) {
this.client = client;
this.ds = ds;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":IN");
try {
System.out.println("IN:User connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (true) {
String lineIn = br.readLine();
byte[] input = lineIn.getBytes();
System.out.println(lineIn);
byte[] output = new byte[4096];
for (int c = 0; c < output.length; c++) output[c] = 0x0;
for (int i = 0; i < input.length && i < output.length; i++) output[i] = input[i];
DatagramPacket dp = new DatagramPacket(output, output.length, InetAddress.getLocalHost(), 4);
ds.send(dp);
}
} catch(Exception e) {
System.out.println("IN:Error connecting to " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
import java.io.*;
导入java.net。*;
导入java.util.*;
公共类消息服务器{
公共静态void main(字符串[]args){
int port=Integer.parseInt(args[0]);
MessageServer ms=newmessageserver();
System.out.println(“在端口“+端口+”上启动服务器”);
ServerSocket ss=null;
试一试{
ss=新服务器套接字(端口);
}捕获(例外e){
System.out.println(“创建服务器时出错:+e.getLocalizedMessage());
系统出口(0);
}
System.out.println(“已创建服务器端口,正在等待用户…”);
socketclient=null;
DatagramSocket ds=null;
试一试{
ds=新的DatagramSocket(4);
}捕获(例外e){
System.out.println(“IN:创建数据报服务器时出错:”+e.getLocalizedMessage());
e、 printStackTrace();
系统出口(0);
}
while(true){
试一试{
client=ss.accept();
System.out.println(“连接用户:+client.getInetAddress().toString());
}捕获(例外e){
System.out.println(“服务器上的错误:+e.getLocalizedMessage());
}
新MessageConnectionIn(客户端,ds).start();
新建MessageConnectionOut(客户端,ds).start();
}
}
}
类MessageConnectionOut扩展线程{
受保护的套接字客户端;
公共数据采集器ds;
公共消息连接输出(套接字客户端、DatagramSocket ds){
this.client=client;
这是1.ds=ds;
}
公开募捐{
this.setName(client.getInetAddress().getHostAddress()+“:OUT”);
试一试{
System.out.println(“out:User connected.”);
DataOutputStream dos=新的DataOutputStream(client.getOutputStream());
while(true){
字节[]传出=新字节[4096];
DatagramPacket dp=新DatagramPacket(传出,传出.length);
ds.接收(dp);
dos.writeChars(新字符串(传出)+“\n”);
}
}捕获(例外e){
System.out.println(“out:Error connecting”+this.getName()+“:”+e.getLocalizedMessage());
返回;
}
}
}
类MessageConnectionIn扩展线程{
受保护的套接字客户端;
公共数据采集器ds;
public MessageConnectionIn(套接字客户端、DatagramSocket ds){
this.client=client;
这是1.ds=ds;
}
公开募捐{
this.setName(client.getInetAddress().getHostAddress()+“:IN”);
试一试{
System.out.println(“IN:User connected.”);
BufferedReader br=新的BufferedReader(新的InputStreamReader(client.getInputStream());
while(true){
字符串lineIn=br.readLine();
byte[]输入=lineIn.getBytes();
系统输出打印项次(行输入);
字节[]输出=新字节[4096];
对于(int c=0;c
更新:
我尝试用多播套接字替换所有DatagramSockets,并在声明MessageServer.main()时将其添加到组中。同样的问题也发生了
多播代码:
public class MessageServer {
public static void main(String[] args) {
int port = Integer.parseInt(args[0]);
MessageServer msgsrv = new MessageServer();
System.out.println("Starting server on port " + port + "...");
ServerSocket ss = null;
try {
ss = new ServerSocket(port);
} catch(Exception e) {
System.out.println("Error creating server: " + e.getLocalizedMessage());
System.exit(0);
}
System.out.println("Created server port, now waiting for users...");
Socket client = null;
MulticastSocket ms = null;
try {
ms = new MulticastSocket(4);
ms.joinGroup(InetAddress.getByName("225.65.65.65"));
} catch(Exception e) {
System.out.println("IN:Error creating Datagram Server: " + e.getLocalizedMessage());
e.printStackTrace();
System.exit(0);
}
while (true) {
try {
client = ss.accept();
System.out.println("Connecting user: " + client.getInetAddress().toString());
} catch(Exception e) {
System.out.println("Error on server: " + e.getLocalizedMessage());
}
new MessageConnectionIn(client, ms).start();
new MessageConnectionOut(client, ms).start();
}
}
}
class MessageConnectionOut extends Thread {
protected Socket client;
public MulticastSocket ms;
public MessageConnectionOut(Socket client, MulticastSocket ms) {
this.client = client;
this.ms = ms;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":OUT");
try {
System.out.println("OUT:User connected.");
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
while (true) {
byte[] outgoing = new byte[4096];
DatagramPacket dp = new DatagramPacket(outgoing, outgoing.length);
ms.receive(dp);
dos.writeChars(new String(outgoing) + "\n");
System.out.println("SENT_TO:" + this.getName());
}
} catch(Exception e) {
System.out.println("OUT:Error connecting " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
class MessageConnectionIn extends Thread {
protected Socket client;
public MulticastSocket ms;
public MessageConnectionIn(Socket client, MulticastSocket ms) {
this.client = client;
this.ms = ms;
}
public void run() {
this.setName(client.getInetAddress().getHostAddress() + ":IN");
try {
System.out.println("IN:User connected.");
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
while (true) {
String lineIn = br.readLine();
byte[] input = lineIn.getBytes();
System.out.println(lineIn);
byte[] output = new byte[4096];
for (int c = 0; c < output.length; c++) output[c] = 0x0;
for (int i = 0; i < input.length && i < output.length; i++) output[i] = input[i];
DatagramPacket dp = new DatagramPacket(output, output.length, InetAddress.getLocalHost(), 4);
ms.send(dp);
}
} catch(Exception e) {
System.out.println("IN:Error connecting to " + this.getName() + ": " + e.getLocalizedMessage());
return;
}
}
}
公共类消息服务器{
公共静态void main(字符串[]args){
int port=Integer.parseInt(args[0]);
MessageServer msgsrv=newmessageserver();
System.out.println(“在端口“+端口+”上启动服务器”);
ServerSocket ss=null;
试一试{
ss=新服务器套接字(端口);
}捕获(例外e){
System.out.println(“创建服务器时出错:+e.getLocalizedMessage());
系统出口(0);
}
System.out.println(“已创建服务器端口,正在等待用户…”);
socketclient=null;
多播套接字ms=null;
试一试{
ms=新的多播套接字(4);
joinGroup女士(InetAddress.getByName(“225.65.65.65”);
}捕获(例外e){
System.out.println(“IN:创建数据报服务器时出错:”+e.getLocalizedMessage());
e、 printStackTrace();
系统出口(0);
}
while(true){
试一试{
client=ss.accept();
System.out.println(“连接用户:+client.getInetAddress().toString());
}捕获(例外e){
System.out.println(“服务器上的错误:”+e.getLocalizedMe
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
private ExecutorService executorService;
public Receiver(InetAddress inetAddress, int port,
ExecutorService executorService) throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
this.executorService = executorService;
}
public void run() {
System.out.println(" @ Receiver ");
System.out.println(" @ Receiver " + this.port);
byte[] buf = new byte[256];
try {
MulticastSocket clientSocket = new MulticastSocket(this.port);
// Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf,
buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
executorService.submit(new Sender(InetAddress
.getByName(INET_ADDR), PORT1, msg));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
private String message;
public Sender(InetAddress inetAddress, int port, String message)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
this.message = message;
}
public void run() {
System.out.println(" @ Sender Address "
+ new String(this.addr.getAddress()));
System.out.println(" @ Sender port " + this.port);
try {
DatagramSocket serverSocket = new DatagramSocket();
String msg = "Sent message no " + message;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(msg.getBytes(),
msg.getBytes().length, this.addr, this.port);
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static class Receiver implements Runnable {
private InetAddress addr;
private int port;
public Receiver(InetAddress inetAddress, int port)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" @ Receiver ");
System.out.println(" @ Receiver port " + this.port);
byte[] buf = new byte[256];
try (MulticastSocket clientSocket = new MulticastSocket(this.port)) {
// Joint the Multicast group.
clientSocket.joinGroup(this.addr);
while (true) {
// Receive the information and print it.
DatagramPacket msgPacket = new DatagramPacket(buf,
buf.length);
clientSocket.receive(msgPacket);
String msg = new String(buf, 0, buf.length);
System.out.println("Socket 1 received msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private static class Sender implements Runnable {
private InetAddress addr;
private int port;
public Sender(InetAddress inetAddress, int port)
throws UnknownHostException {
this.addr = InetAddress.getByName(INET_ADDR);
this.port = port;
}
public void run() {
System.out.println(" @ Sender Address "
+ new String(this.addr.getAddress()));
System.out.println(" @ Sender port " + this.port);
// Open a new DatagramSocket, which will be used to send the data.
try {
DatagramSocket serverSocket = new DatagramSocket();
for (int i = 0; i < 5; i++) {
System.out.println("inside loop");
String msg = "Sent message no 2" + i;
// Create a packet that will contain the data
// (in the form of bytes) and send it.
DatagramPacket msgPacket = new DatagramPacket(
msg.getBytes(), msg.getBytes().length, this.addr,
this.port);
System.out.println("Before sending to socket");
serverSocket.send(msgPacket);
System.out.println("Server sent packet with msg: " + msg);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}