socket实现简单的多人聊天室

服务端Server.java

package chatDemo;

import java.awt.BorderLayout;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map.Entry;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;


public class Server extends JFrame {
	private JTextArea txt = new JTextArea("服务器已经启动");
	private ServerSocket serverSocket = null;
	private static Map<Socket, Integer> list = new LinkedHashMap<Socket,Integer>();	
	private ExecutorService exec= null;
	
	public Server() throws IOException{
		setLayout(new BorderLayout());
		this.add(new JScrollPane(txt),BorderLayout.CENTER);
		setSize(500,300);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		
		//启动服务器
		serverSocket = new ServerSocket(54321);
		//创建线程池
		exec = Executors.newCachedThreadPool();
		//服务器通过accept()方法产生阻塞,接受客户端连接   
		while(true){
			//构造器也是一个进程?不然这里while会把主线程卡死?
			Socket socket = null;
			//接收到客户端连接
			socket = serverSocket.accept();
			System.out.println(1);
			//将每次连接的client加入到list中。
			list.put(socket,socket.getPort());
			//启动线程,用于不停地从服务器端读取数据
			exec.execute(new Communication(socket));
		}
	}
	
	public class Communication implements Runnable {
		private Socket socket;
		//用于接收从客户端发送过来的信息
		private DataInputStream fromClient =null;
		//用于向客户端发送信息
		private DataOutputStream toClient = null;
		private String msg;
		
		public Communication(Socket socket) throws IOException{
			this.socket = socket;
			fromClient = new DataInputStream(socket.getInputStream());
			msg ="["+socket.getPort()+ "]已连接到服务器";
			txt.append(msg+"\n");
			sendMessage();
			msg="";
		}
		
		@Override
		public void run() {
			try {
				while((msg= fromClient.readUTF())!=null){
					msg = "[" + socket.getPort() + "]:"+ msg;
					txt.append(msg+"\n");
					sendMessage();
				}
			} catch (Exception e) {
			}
			
		}
		
		//将从客服端接收到的信息,循环发送到所有客户端
		public void sendMessage()  {
			Iterator it = list.entrySet().iterator();
			while (it.hasNext()) {
				Entry entry = (Entry) it.next();
				Socket client =(Socket) entry.getKey();
				int port = (Integer) entry.getValue();
				//如果部分客户端关闭了,此处如果用throws exception数据将无法发送打客户端,用try catch可以继续通信
				try{
					toClient = new DataOutputStream(client.getOutputStream());
					toClient.writeUTF(msg);	
				} catch (IOException e) {
					e.printStackTrace();
				}					
			}
		}
	}
	
	public static void main(String[] args) throws IOException {
		Server server = new Server();
	}
}



客户端Client.java

package chatDemo;

import java.awt.BorderLayout;
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;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.Border;

public class Client extends JFrame{
	private JButton conn = new JButton("connect");
	private JTextArea txt = new JTextArea("");
	private JTextField edt = new JTextField("");
	private JButton send = new JButton("发送");
	private JPanel p1 = new JPanel();
	private JPanel p2 = new JPanel();
	private ExecutorService exec= null;
	private Socket clientSocket = null;
	private DataInputStream fromServer;
	private DataOutputStream toServer;
	
	public Client(){
		setLayout(new BorderLayout());
		p1.setLayout(new BorderLayout());
		p2.setLayout(new BorderLayout());
		p1.add(edt,BorderLayout.CENTER);
		p1.add(send,BorderLayout.EAST);
		
		p2.add(new JScrollPane(txt),BorderLayout.CENTER);
		p2.add(p1,BorderLayout.SOUTH);
		p2.add(conn,BorderLayout.NORTH);

		this.add(p2,BorderLayout.CENTER);
		setSize(500,300);
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		//启动客户端,连接到服务器
		conn.addActionListener(new ActionListener() {		
			@Override
			public void actionPerformed(ActionEvent e) {
				//创建线程池,并执行线程
				exec = Executors.newCachedThreadPool();	
				exec.execute(new ClientSocket());
			}
		});
		
		//往服务器发送数据
		send.addActionListener(new ActionListener() {		
			@Override
			public void actionPerformed(ActionEvent e) {
				try {
					toServer.writeUTF(edt.getText());
					toServer.flush();
					edt.setText("");
				} catch (UnknownHostException e1) {
					e1.printStackTrace();
				} catch (IOException e1) {
					e1.printStackTrace();
				}	
			}
		});
		
	}
	
	//创建客户端socket线程,用于不停地读取服务器发送过来 的数据
	class ClientSocket implements Runnable{	
		@Override
		public void run() {
			try {
				clientSocket = new Socket("localhost", 54321);
				fromServer = new DataInputStream(clientSocket.getInputStream());
				toServer = new DataOutputStream(clientSocket.getOutputStream());	
				
				while (true) {
					String msg = fromServer.readUTF();
					if (msg != null)
						txt.append(msg + "\n");
				}
			} catch (UnknownHostException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}			
		}
	}
	
	public static void main(String[] args) {
		Client client = new Client();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值