[英]Java: Sending data from a server to all clients listening on the socket
[英]Send data from server to all clients in socket programming in Java
我有一个客户端和服务器 class,客户端有 GUI。 如果我打开服务器然后打开客户端,一切正常。 但是如果我打开服务器和两个客户端,客户端不会互相发送消息,只会与回显客户端之类的服务器发送消息。 我想我在我的代码中跳过了一些细节,但我不知道我错在哪里。
客户
package program;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class gui
{
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream out = null;
public String data = "0";
server _server;
JFrame pencere;
JButton button;
JTextArea area;
JTextField type;
public gui(){
try
{
socket = new Socket("127.0.0.1",4000);
System.out.println("Connected");
// takes input from terminal
input = new DataInputStream(socket.getInputStream());
// sends output to the socket
out = new DataOutputStream(socket.getOutputStream());
}
catch(UnknownHostException u)
{
System.out.println(u);
}
catch(IOException i)
{
System.out.println(i);
}
pencere = new JFrame("oxChat");
pencere.setSize(640,480);
pencere.setLayout(null);
button = new JButton("gönder");
button.addActionListener( new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
try {
out.writeUTF(type.getText());
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
area = new JTextArea();
type = new JTextField();
pencere.add(type);
pencere.add(area);
pencere.add(button);
area.setBounds(0,0,640,350);
type.setBounds(0,370,640,25);
button.setBounds(640/2-80/2,400,80,30);
pencere.setVisible(true);
pencere.setResizable(false);
pencere.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new Thread (new dagitici(socket,this)).start();
}
public static void main(String[] args) throws IOException {
gui app = new gui();
}
String getData(){
return data;
}
void setData(String dataa){
this.data = dataa;
area.append(this.data+"\n");
}
}
class dagitici extends Thread{
private Socket socket = null;
private DataInputStream input = null;
private DataOutputStream out = null;
gui g;
public String okunan="";
public dagitici(Socket socket,gui g){
this.socket = socket;
this.g = g;
}
@Override
public void run() {
try {
input = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
while(true){
try {
System.out.println("a");
okunan=input.readUTF();
g.setData(okunan);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务器
package program;
// A Java program for a Server
import com.sun.jdi.PathSearchingVirtualMachine;
import javax.swing.*;
import java.net.*;
import java.io.*;
public class server
{
private Socket socket;
private ServerSocket server;
public static String data;
// constructor with port
public void start(int port){
try {
server = new ServerSocket(port);
while(true){
socket = server.accept();
new Thread (new ConnectionHandler(socket)).start();
}
}catch(IOException i){
}
}
public static void main(String[] args) {
server _server = new server();
_server.start(4000);
}
}
class ConnectionHandler extends Thread{
gui app;
private String data;
private Socket socket = null;
private DataInputStream in = null;
private DataOutputStream out = null;
public ConnectionHandler(Socket socket){
this.socket=socket;
}
@Override
public void run() {
try
{
System.out.println("Waiting for a client ...");
System.out.println("Client accepted");
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
out = new DataOutputStream(socket.getOutputStream());
String line = "";
// reads message from client until "Over" is sent
while (!line.equals("Over"))
{
try
{
line = in.readUTF();
out.writeUTF(line);
}
catch(IOException i)
{
System.out.println(i);
}
}
System.out.println("Closing connection");
// close connection
socket.close();
in.close();
}
catch(IOException i)
{
System.out.println(i);
}
}
public String getServerData(){
return data;
}
}
将List<ConnectionHandler>
添加到您的服务器 class:
List<ConnectionHandler> clients = new ArrayList<>();
为了更好的衡量,一个锁:
Object lock = new Object();
然后我们需要将任何新连接的客户端添加到该列表中:
socket = server.accept(); ConnectionHandler client = new ConnectionHandler(this, socket) synchronized (lock) { clients.add(client); } new Thread(client).start();
现在我们只需要一个方法来分发服务器 class 中的所有传入消息:
void distributeMessage(String message) { List<ConnectionHandler> clientsCopy; synchronized (lock) { clientsCopy = new ArrayList<>(clients); } for (ConnectionHandler client: clientsCopy) { client.sendMessage(message); } }
现在我们需要更改 ConnectionHandler,我们首先清理字段:
private Socket socket; private DataInputStream in; private DataOutputStream out; private server server;
这些都是我们需要的领域。
接下来我们需要更改这个 class 的构造函数:
public ConnectionHandler(server server, Socket socket) { this.server = server; this.socket = socket; this.in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); this.out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); }
如果可能,所有字段都应在构造函数中初始化。
然后我们必须添加新的sendMessage(String message)
方法:
public void sendMessage(String message) { try { out.writeUTF(message); out.flush(); } catch (IOException e) { // TODO: Here you HAVE to check if the connection was closed // And if it was closed, call a method in the server class to // remove this client. e.printStackTrace(); } }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.