socket网络编程--简单的多人聊天

//本代码参考于马士兵的代码,做了一些简单的改动,例如获取主机名称好让用户知道那句话是谁发的,Swing方面基本上全改了,关键地方加了我所理解的注释,关键线程方面的代码基本上用马老师的

//服务器端代码
import java.awt.FlowLayout;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class QLServer extends JFrame{
	public JTextArea jtextarea = null;
	public void lanuchFrame(String str){
		this.setName(str);
		init();
	}
	private void init() {
		setLayout(new FlowLayout());
		jtextarea =new JTextArea(20, 17);
		jtextarea.setLineWrap(true);
		jtextarea.setEditable(false);
		this.getContentPane().add(new JScrollPane(jtextarea));
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(200,400);
		setLocationRelativeTo(null);
		setResizable(false);
	}
	ServerSocket server = null;
	Collection cClients = new ArrayList();//加个泛型
	public void startServer() throws IOException{
		while(true){
			Socket s = server.accept();
			cClients.add(new ClientConn(s));
			jtextarea.append("new client login" + s.getInetAddress() + ":" + s.getPort()+"\n");
		}
	}
	
	public QLServer(int port,String str) throws IOException{
		server = new ServerSocket(port);
		lanuchFrame(str);
	}
	
	class ClientConn implements Runnable
	{
		Socket s = null;
		public ClientConn(Socket s)
		{
			this.s = s;
			(new Thread(this)).start();
		}
		
		public void send(String str) throws IOException
		{
			
			DataOutputStream dos = new DataOutputStream(s.getOutputStream());
			dos.writeUTF(str);
		}
		
		public void dispose()//客户端下线
		{
			try {
				if (s != null) s.close();
				cClients.remove(this);
				jtextarea.append("A client out! \n");
				jtextarea.append("client count: " + cClients.size() + "\n\n");
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}
		
		public void run()
		{
			try {
				DataInputStream dis = new DataInputStream(s.getInputStream());
				String str = dis.readUTF();
				while(str != null && str.length() !=0)
				{
					System.out.println(str);
					for(Iterator it = cClients.iterator(); it.hasNext(); )
					{
						ClientConn cc = (ClientConn)it.next();
						if(this != cc)
						{
							cc.send(str+" "+s.getInetAddress().getHostName());
						}
					}
					str = dis.readUTF();//少了这句话会无限输出
					//send(str);
				}
				this.dispose();
			} 
			catch (Exception e) 
			{
				this.dispose();
			}
			
		}
	}
public static void main(String[] args) {
	try {
		QLServer qlserver = new QLServer(8888,"QLServer");
		qlserver.startServer();
	} catch (IOException e) {
		e.printStackTrace();
	}
	
}
}
===============================

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
//客户端代码
public class QLClient extends JFrame implements ActionListener{
	public JTextArea jtextarea1 = null;
	public JTextArea jtextarea2 = null;
	public JButton button = null;
	Socket s =null;
	public void launchFrame(String str){
		this.setName(str);
		init();
	}
	public QLClient(String str) throws IOException{
		launchFrame(str);
		s = new Socket("127.0.0.1",8888);//哪台电脑做服务器,IP地址改成那台机子的IP
		(new Thread(new ServeConn())).start();
	}
	private void init() {
		setLayout(new FlowLayout());
		jtextarea1 =new JTextArea(17, 16);
		jtextarea2 =new JTextArea(4, 16);
		jtextarea1.setLineWrap(true);
		jtextarea1.setEditable(false);
		jtextarea2.setLineWrap(true);
		button = new JButton("发送");
		button.addActionListener(this);//绑定button事件
		this.getContentPane().add(new JScrollPane(jtextarea1));
		this.getContentPane().add(new JScrollPane(jtextarea2));
		add(button);
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setSize(200,470);
		setLocationRelativeTo(null);
		setResizable(false);
		
	}
	public void send(String str) throws IOException{
		DataOutputStream dos = new DataOutputStream(s.getOutputStream());
		dos.writeUTF(str);
	}

	public void actionPerformed(ActionEvent e) {
		if(e.getSource()==button){
			String sendStr = jtextarea2.getText();
			if(sendStr.trim().length()==0){
				return;
			}
			try {
				this.send(sendStr);
				jtextarea2.setText("");
				InetAddress a;
				a = InetAddress.getLocalHost();
				String hostname = a.getHostName();
				jtextarea1.append(sendStr+"("+hostname+")"+"\n");
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
	}
	
	class ServeConn implements Runnable{
		public void run() {
			if(s == null) return;
			try {
				DataInputStream dis = new DataInputStream(s.getInputStream());
				String str = dis.readUTF();
				while (str != null && str.length() != 0)
				{
					//System.out.println(str);
					QLClient.this.jtextarea1.append(str + "\n");//内部类用外类中的变量或方法加外类名
					str = dis.readUTF();
				}
			} 
			catch (Exception e)
			{
				e.printStackTrace();
			}
		}
	}
	//main主函数入口
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		QLClient qlclient = new QLClient("QLClient");
		String str = br.readLine();
		while(str!=null&&str.length()!=0){
			qlclient.send(str);
			str = br.readLine();//防止死循环
		}
		qlclient.s.close();
	}
}

以上代码供参考,关于异常基本上没有处理,所以操作顺序不对可能会出现异常。

你可能感兴趣的:(java)