100分求助Socket网络编程
现在想做一个类似于QQ群功能程序,做的过程遇到很多问题
Server类只需要实现接受每个client类的传出的信息,并且打印在自己的信息板上,
然后将接受的信息发送给每个client
也就是说,每个client能看到彼此发送的信息,功能类似于QQ群
client的功能一是打印自己输出的信息,二是接受Server传过来的信息,打印出来
初学网络编程,欢迎拍砖
下面是代码
Server 类
package ex30;import javax.swing.*;import java.io.*;import java.io.IOException;import java.net.*;import java.util.*;public class Ex30_13Server extends JFrame{ private JTextArea jtaServer = new JTextArea(); private BufferedReader input; private String sendMessage = ""; private ArrayList<Socket> socketArray = new ArrayList<Socket>(); public Ex30_13Server(){ jtaServer.setEditable(false); add(new JScrollPane(jtaServer)); setTitle("MultiThreadServer"); setSize(700, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); try{ ServerSocket serverSocket = new ServerSocket(8000); while(true){ Socket socket = serverSocket.accept(); InetAddress inetAddress = socket.getInetAddress(); jtaServer.append(inetAddress.getHostName() + " connected " + new Date()); socketArray.add(socket); MutiUser mu = new MutiUser(socket); mu.start(); } } catch(Exception ex){ ex.printStackTrace(); } } // Define the thread class for send message class SendTask implements Runnable{ public void run(){ try{ while(true){ if(!sendMessage.isEmpty()){ for(Socket socket : socketArray){ // 将接受的信息输出到每个客户端上 PrintWriter outputToEachClient = new PrintWriter(socket.getOutputStream()); outputToEachClient.println(sendMessage); } sendMessage = ""; } } } catch(Exception ex){ ex.printStackTrace(); } } } // Define the thread class for receive message class ReceiveTask implements Runnable{ public void run(){ try{ while(true){ String receiveMessage = input.readLine(); if(!receiveMessage.isEmpty()){ jtaServer.append(receiveMessage + "\n"); sendMessage = receiveMessage; } } } catch(IOException ex){ ex.printStackTrace(); } } } class MutiUser extends Thread{ private Socket server; public MutiUser(Socket server){ this.server = server; } public void run(){ try{ input = new BufferedReader(new InputStreamReader(server.getInputStream())); new Thread(new SendTask()).start(); new Thread(new ReceiveTask()).start(); } catch(Exception ex){ ex.printStackTrace(); } } } public static void main(String[] args) { // TODO 自动生成方法存根 new Ex30_13Server(); }}
package ex30;import javax.swing.*;import ex30.Ex30_12Client.ReceiveTask;import ex30.Ex30_12Client.SendTask;import java.io.*;import java.awt.*;import java.awt.event.*;import java.net.*;public class Ex30_13Client extends JFrame{ private JLabel jlblName = new JLabel("Name"); private JLabel jlblText = new JLabel("Enter text"); private JTextField jtfName = new JTextField(); private JTextField jtfText = new JTextField(); private JTextArea jtaClient = new JTextArea(); private PrintWriter output; private BufferedReader input; private String sendMessage = ""; public Ex30_13Client(){ JPanel panel1 = new JPanel(new GridLayout(2, 1)); panel1.add(jlblName); panel1.add(jlblText); JPanel panel2 = new JPanel(new GridLayout(2, 1)); panel2.add(jtfName); panel2.add(jtfText); JPanel panel = new JPanel(new BorderLayout()); panel.add(panel1, BorderLayout.WEST); panel.add(panel2, BorderLayout.CENTER); setLayout(new BorderLayout()); add(panel, BorderLayout.NORTH); add(jtaClient, BorderLayout.CENTER); jtaClient.setEditable(false); setTitle("Ex30_13Client");; setSize(500, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); setVisible(true); jtfText.addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent e){ if(e.getKeyCode() == KeyEvent.VK_ENTER){ String text = jtfText.getText(); if(!text.isEmpty()){ sendMessage = jtfName.getText() + ":" + text; output.println(sendMessage); output.flush(); System.out.println(sendMessage); jtfText.setText(""); } } } }); try{ Socket socket = new Socket("localhost", 8000); output = new PrintWriter(socket.getOutputStream()); input = new BufferedReader(new InputStreamReader(socket.getInputStream())); new Thread(new SendTask()).start(); new Thread(new ReceiveTask()).start(); } catch (Exception ex){ ex.printStackTrace(); } } class SendTask implements Runnable{ public void run(){ try{ while(true){ if(!sendMessage.isEmpty()){ jtaClient.append(sendMessage + "\n"); sendMessage = ""; } } } catch(Exception ex){ ex.printStackTrace(); } } } class ReceiveTask implements Runnable{ public void run(){ try{ while(true){ String receiveMessage = input.readLine(); jtaClient.append(receiveMessage + "\n"); } } catch(Exception ex){ ex.printStackTrace(); } } } public static void main(String[] args) { // TODO 自动生成方法存根 new Ex30_13Client(); }}
package ex40;import javax.swing.*;import java.io.*;import java.io.IOException;import java.net.*;import java.util.*;public class Ex30_13Server extends JFrame { private JTextArea jtaServer = new JTextArea(); private String sendMessage = ""; private ArrayList<Socket> socketArray = new ArrayList<Socket>(); public Ex30_13Server() { jtaServer.setEditable(false); add(new JScrollPane(jtaServer)); setTitle("MultiThreadServer"); setSize(700, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); try { ServerSocket serverSocket = new ServerSocket(8000); while (true) { Socket socket = serverSocket.accept(); InetAddress inetAddress = socket.getInetAddress(); jtaServer.append(inetAddress.getHostName() + " connected " + new Date()); socketArray.add(socket); MutiUser mu = new MutiUser(socket); mu.start(); } } catch (Exception ex) { ex.printStackTrace(); } } // Define the thread class for send message class SendTask implements Runnable { private MutiUser mu; public SendTask(MutiUser mu) { this.mu=mu; } public void run() { try { while (true) { if (!sendMessage.isEmpty()) { for (Socket socket : socketArray) { // 将接受的信息输出到每个客户端上 PrintWriter outputToEachClient = new PrintWriter( socket.getOutputStream()); outputToEachClient.println(sendMessage); } sendMessage = ""; } } } catch (Exception ex) { ex.printStackTrace(); } } } // Define the thread class for receive message class ReceiveTask implements Runnable { private MutiUser mu; public ReceiveTask(MutiUser mu) { this.mu=mu; } public void run() { try { while (true) { String receiveMessage = mu.input.readLine(); if (!receiveMessage.isEmpty()) { jtaServer.append(receiveMessage + "\n"); sendMessage = receiveMessage; } } } catch (IOException ex) { ex.printStackTrace(); } } } class MutiUser extends Thread { private Socket server; private BufferedReader input; public MutiUser(Socket server) { this.server = server; } public void run() { try { input = new BufferedReader(new InputStreamReader( server.getInputStream())); new Thread(new SendTask(this)).start(); new Thread(new ReceiveTask(this)).start(); } catch (Exception ex) { ex.printStackTrace(); } } } public static void main(String[] args) { // TODO 自动生成方法存根 new Ex30_13Server(); }}
[解决办法]
闲来无事帮你改了改,服务器端改得多点,客户端基本没动,能完成你要的功能了
package ex30;import javax.swing.*;import java.io.*;import java.io.IOException;import java.net.*;import java.util.*;import java.util.concurrent.ConcurrentLinkedQueue;public class Ex30_13Server extends JFrame implements Runnable{ private JTextArea jtaServer = new JTextArea(); private BufferedReader input; private String sendMessage = ""; private ConcurrentLinkedQueue<String> messageQueue = null; private ArrayList<Socket> socketArray = new ArrayList<Socket>(); public Ex30_13Server(){ jtaServer.setEditable(false); add(new JScrollPane(jtaServer)); setTitle("MultiThreadServer"); setSize(700, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); this.messageQueue = new ConcurrentLinkedQueue<String>(); new Thread(this).start(); } @Override public void run() { ServerSocket serverSocket = null; try{ serverSocket = new ServerSocket(8000); new Thread(new broadcaster()).start(); while(true){ Socket socket = serverSocket.accept(); InetAddress inetAddress = socket.getInetAddress(); synchronized (socketArray){ socketArray.add(socket); } new Thread( new UserInput(socket)).start(); synchronized (jtaServer) { jtaServer.append(inetAddress.getHostName() + " connected " + new Date()+ "\n"); } } } catch(Exception ex){ ex.printStackTrace(); } finally { try { serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } } class broadcaster implements Runnable{ @Override public void run() { while (true){ if (!messageQueue.isEmpty()){ synchronized (socketArray){ try { String message = messageQueue.poll(); for(Socket socket : socketArray){ // 将接受的信息输出到每个客户端上 PrintWriter outputToEachClient = new PrintWriter(socket.getOutputStream()); outputToEachClient.println(message); outputToEachClient.flush(); } } catch (IOException e) { e.printStackTrace(); } } } } } } class UserInput implements Runnable { private Socket socket; public UserInput(Socket socket){ this.socket = socket; } @Override public void run() { try { BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); String inputLine = null; while (true){ while ((inputLine = in.readLine()) != null) { messageQueue.add(inputLine); jtaServer.append(inputLine+"\n"); } } } catch (Exception e) { //e.printStackTrace(); } finally { try { socket.close(); synchronized (socketArray){ socketArray.remove(socket); } } catch (IOException e1) { System.out.println("Can not close socket"); } } } } public static void main(String[] args) { // TODO 自动生成方法存根 new Ex30_13Server(); }}
[解决办法]
楼上的是正确的,改了几次楼主的代码,发现楼主对对象的使用存在些问题,可以学习
[解决办法]
只是为了服务监听放在单独的线程