zoukankan      html  css  js  c++  java
  • java项目-----客户端与客户端通信--实现群聊功能的代码

    这是这个网络聊天室项目的原理图:

    很简单,首先ABCD是4个客户端,当A发送信息给服务器,服务器实现以广播的形式把信息全发给每个人---群发群聊

    客户端代码:

    package com.aa;
    
    import java.awt.Color;
    import java.awt.FlowLayout;
    import java.awt.Image;
    import java.awt.Toolkit;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.io.*;
    import java.net.*;
    import java.util.Date;
    import java.awt.BorderLayout;
    
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.UIManager;
    
    public class Client {
    	public static void initUIManager() {
    		try {
    			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    		} catch (Exception e) {
    			System.err.println("获取系统外观失败:" + e);
    		}
    	}
    
    	public static void main(String[] args) {
    		initUIManager();
    		new ClientFrame();
    	}
    }
    
    class ClientFrame extends JFrame implements Runnable, ActionListener,
    		KeyListener {
    
    	private static final long serialVersionUID = 8518610966119429018L;
    	ImageIcon image;// 定义一个图片
    	JPanel panel;
    	JLabel label;
    	JFrame frame;// 改变窗体的大小
    	JScrollPane textPane;
    	JTextArea areaText;
    	// 加滚动轴代码
    	JTextField fieldMsg;
    	JButton butSend;
    	JButton butConnect;
    	Socket socket;
    	DataInputStream in;
    	DataOutputStream out;
    	Thread thread;
    
    	public static int WIDTH = 500;
    	public static int HEIGHT = 400;
    	public static String title = "Client";
    
    	private static final String IP_ADDRESS = "127.0.0.1";
    
    	public ClientFrame() {
    		init();
    		setTitle("客户端");
    		setSize(480, 400);//
    		setLocationRelativeTo(null);
    		setVisible(true);
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    	}// 首先确定插入一张图片
    
    	public void init() {// /
    		setLayout(null);
    		image = new ImageIcon("90.jpg");//
    		label = new JLabel(image);
    		label.setBounds(173, 0, 415, 324);
    		panel = new JPanel();//
    		areaText = new JTextArea();
    		this.setResizable(false);
    		panel.add(areaText);
    		areaText.setLineWrap(true);
    		areaText.setEditable(false);
    		textPane = new JScrollPane(areaText);
    
    		// 客户端 (Client) (通常是一个采用图形用//界面的程序)与服务器 (Server) 区分开来。
    
    		butSend = new JButton("Send");
    		butSend.addKeyListener(this);// 设置按钮监听器
    		fieldMsg = new JTextField(150);
    		butSend.addActionListener(this);
    		butConnect = new JButton("Connect");
    		butConnect.addActionListener(this);
    		areaText.setBackground(Color.yellow);// /该背景色
    		// 设置文本区域的大小
    		areaText.setBounds(0, 0, 287, 321);// /修改文本域的大小
    		textPane.setBounds(5, 5, 475, 320);
    		fieldMsg.setBounds(5, 330, 280, 24);
    		butSend.setBounds(299, 330, 80, 24);
    		butConnect.setBounds(394, 330, 80, 24);
    		add(panel);
    		add(label, BorderLayout.EAST);
    		add(areaText);//
    		add(textPane);//
    		add(butSend);
    		add(butConnect);
    		add(fieldMsg);
    
    		Toolkit kit = Toolkit.getDefaultToolkit();
    		Image imge = kit.getImage("27.jpg");
    		this.setIconImage(imge);
    
    		fieldMsg.addKeyListener(this);
    
    		socket = new Socket();// 客户端对象
    		thread = new Thread(this);
    	}
    
    	//
    	public void startSocket() {// (一)核心
    		try {// 向服务器端发送一个连接请求,跟服务器创建一个连接
    			if (!socket.isConnected()) {//
    				InetAddress address = InetAddress.getByName(IP_ADDRESS);
    				InetSocketAddress socketAddress = new InetSocketAddress(// 是.net包中的一个类
    						address, 4339);// 根据ip地址和端口号创建套接字地址
    				socket.connect(socketAddress);
    				in = new DataInputStream(socket.getInputStream());
    				out = new DataOutputStream(socket.getOutputStream());
    				butSend.setEnabled(true);
    				if (!(thread.isAlive())) {
    					thread = new Thread(this);
    				}
    				thread.start();
    			}
    		} catch (Exception e) {
    			System.out.println(e);
    			socket = new Socket();
    
    		}
    
    	}
    
    	public void send() {
    		String msg = fieldMsg.getText().trim();
    		if (msg.isEmpty()) {
    			JOptionPane.showMessageDialog(this,
    					"Please input you message before sending.");
    			return;
    		}
    		// areaText.append("Client: " + msg + "
    ");
    		fieldMsg.setText("");
    		try {
    			Date d = new Date();
    			out.writeUTF("
    " + msg + "
    " + d.toLocaleString());// 这是发送给服务器的
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	@Override
    	public void actionPerformed(ActionEvent arg0) {// 使用此方法判断
    		if (arg0.getSource() == butSend) {
    			send();
    		} else if (arg0.getSource() == butConnect) {
    			startSocket();
    		}
    	}
    
    	@Override
    	public void run() {// 这和send方法有何先后顺序,服务端程序运行后,客户端该最哪些动作,同时服务器端程序是怎样的?
    		if (Thread.currentThread() == thread) {
    			String msg = null;
    			while (true) {// 循环接收服务器端发送的信息并显示在文本区
    				try { // /核心(二)
    					msg = in.readUTF();//
    					areaText.append("Client: " + msg + "
    ");// 我曾修改过
    				} catch (IOException e) {
    					e.printStackTrace();
    					socket = new Socket();
    					break;
    				}
    			}
    		}
    	}
    
    	@Override
    	public void keyPressed(KeyEvent arg0) {
    		if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
    			send();
    		}
    	}
    
    	@Override
    	public void keyReleased(KeyEvent arg0) {
    
    	}
    
    	@Override
    	public void keyTyped(KeyEvent arg0) {
    
    	}
    
    }
    

      服务器端代码:

    package com.aa;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.EOFException;
    import java.io.IOException;
    import java.net.BindException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.SocketException;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Server {
    	boolean started = false;
    	ServerSocket ss = null;
    	List<ChatClient> clients = new ArrayList<ChatClient>(); // 保存客户端线程类list是一个接口,Arraylist是一个类
    
    	// ArrayList是一个集合类。类里面可以放很多对象。 clients.size是指的是有多少个对象
    	public static void main(String[] args) {
    		new Server().start();
    	}
    
    	void start() {
    		try {
    			ss = new ServerSocket(4339); // 建立服务端对象
    			started = true;
    		} catch (BindException e) {//创建对象后,需要做异常处理,以便程序出错时,做出响应
    			System.out.println("端口使用中");
    		} catch (IOException e) {
    			e.printStackTrace();// 
    		} // 死循环
    		try {// 核心(一)
    
    			while (started) {
    				Socket s = ss.accept(); // 监听客户端发来的请求/
    										
    				ChatClient c = new ChatClient(s); 
    									
    				System.out.println("客戶端接收成功");
    				new Thread(c).start(); 
    										
    				clients.add(c); 
    							
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				ss.close();
    			} catch (IOException e) {
    			
    				e.printStackTrace();
    			}
    		}
    	}
    
    	// 这个类的作用
    	// 建立客户端线程接收,发送数据多线程的所以要实现Runnable接口
    	class ChatClient implements Runnable {
    		private Socket s;
    		DataInputStream dis = null;
    		DataOutputStream dos = null;
    		boolean bConnected = false;
    
    		public ChatClient(Socket s) {
    			this.s = s;
    			try {// 用来接收客户端发来数据的输入流
    				dis = new DataInputStream(s.getInputStream());
    				// 服务器向客户端发送数据的输出流
    				dos = new DataOutputStream(s.getOutputStream());
    				bConnected = true;
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    
    		public void send(String str) {
    			try {
    				dos.writeUTF(str);// *这也是服务器发送给客户端的
    			} catch (SocketException e) {
    				System.out.println("對方退出了");//
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    
    		//
    		public void run() {// 核心(二) //实现接口,就必须重写接口里的方法
    			try {
    				while (bConnected) {
    					String str = dis.readUTF();// *是阻塞式的,没有发过来信息,就死死等着,
    					for (int i = 0; i < clients.size(); i++) {
    						ChatClient c = clients.get(i);// 服务器端获取多少个客户端与他连接,将信息发送给每一个客户端
    						c.send(str);//
    					}
    				}
    			} catch (EOFException e) {
    				System.out.println("客戶端退出了");
    			} catch (IOException e) {
    				e.printStackTrace();
    			} finally {
    				if (dis != null)
    					if (s != null)//
    						try {//
    							dis.close();
    							s.close();
    							dos.close();
    						} catch (IOException e) {
    							e.printStackTrace();
    						}
    			}
    		}
    	}
    }
    

      

  • 相关阅读:
    补交20145226蓝墨云班课 -- 程序设计中临时变量的使用
    补交20145226蓝墨云班课 -- MyCP
    补交20145226蓝墨云班课 -- MyOD
    补交20145226蓝墨云班课 -- Arrays和String单元测试
    补交20145226蓝墨云班课 -- 后缀表达式
    20145226夏艺华 《Java程序设计》 课堂实践
    20145226夏艺华 网络对抗技术 EXP9 web安全基础实践
    (转载)充分理解QML的属性绑定
    (转载)UML类图中的六大关系:关联、聚合、组合、依赖、继承、实现
    (转载)链路层MTU的概念?为什么MTU值普遍都是1500?
  • 原文地址:https://www.cnblogs.com/langlove/p/3484622.html
Copyright © 2011-2022 走看看