聊天程序初级版

来源:互联网 发布:7位铁通卡用什么网络 编辑:程序博客网 时间:2024/05/22 08:24
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.util.ArrayList;import java.util.Iterator;import java.util.List;public class ChatServer {/** * 8.2、接收多个信息,建立两个条件判断 */boolean started = false; ServerSocket ss = null;List<Client> clients = new ArrayList<Client>();public static void main(String[] args) {new ChatServer().start();}public void start() {/** * 5、创建服务端的连接端口号ServerSocket,并接受客户端的连接accept * 打印System.out.println("a client connetion")作为测试 */try{ss = new ServerSocket(8888);started = true; //创建端口后为真} catch (BindException e) {System.out.println("端口被占用");System.out.println("请关闭程序,重启服务器");System.exit(0);} catch (IOException e) {e.printStackTrace();}try {while(started){Socket s = ss.accept();System.out.println("a client connetion");Client c = new Client(s);new Thread(c).start();clients.add(c);}} catch (IOException e){e.printStackTrace();} finally {try {ss.close();} catch (IOException e) {e.printStackTrace();}}}/** * 10、建立线程处理客户端 */class Client implements Runnable{private Socket s;private DataInputStream dis = null;private DataOutputStream dos = null;private boolean bConnected = false; public Client(Socket s){this.s = s;/** * 7.2、建立输入流,读取客户端输入的数据 */try{dis = new DataInputStream(s.getInputStream());dos = new DataOutputStream(s.getOutputStream());bConnected = true;  //接收到连接后为真}  catch (IOException e){e.printStackTrace();}}/** * 11、服务端接收客户端信息并发送给客户端 */public void send(String str) {try {dos.writeUTF(str);} catch (IOException e) {clients.remove(this);  //当其中一个client退出的时候要移除list里面的内容,移除当前对象的内容,用this。System.out.println("对方已退出!");}}@Overridepublic void run() {try {while(bConnected) {String str = dis.readUTF();System.out.println(str);for(int i = 0;i<clients.size();i++){Client c = clients.get(i);c.send(str);}/*for(Iterator<Client> it = clients.iterator();it.hasNext();) {Client c = it.next();c.send(str);}Iterator<Client> it = clients.iterator();while(it.hasNext()){Client c =it.next();c.send(str);}*/}} catch (EOFException e) {System.out.println("client closed");} catch (IOException e){e.printStackTrace();/** * 9、调整bug,将程序写得更健壮,打印友好提示信息 */} finally {try {if(dis != null){dis.close();}if(dos != null){dos.close();}if(s != null) {s.close();}} catch (IOException e) {e.printStackTrace();}}}}}
import java.awt.BorderLayout;import java.awt.Frame;import java.awt.TextArea;import java.awt.TextField;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;import java.net.SocketException;import java.net.UnknownHostException;public class ChatClient extends Frame {Socket s = null;  //成员变量,方便拿到socket里面的内容DataOutputStream dos = null;DataInputStream dis = null;private boolean bConnected = false;Thread tRecv = new Thread(new RecvThread());/** * 2、添加TextField文本输入框,添加TestArea下拉条 */TextField tfTex = new TextField();TextArea taContent = new TextArea();public static void main(String[] args) {new ChatClient().luanchFrame();}public void luanchFrame(){/** * 1、首先创建窗口 */this.setLocation(300, 400);this.setSize(400, 500);this.add(tfTex, BorderLayout.SOUTH);  //两个参数,设定传入的方向,BorderLayout区域划分为:东西南北中this.add(taContent, BorderLayout.EAST);pack();  //将区域包裹,不留空白区域/** * 3、添加窗口关闭的功能,这里使用匿名类(没有名字的类)。(其它两种,并排的监听器类、内部类) */this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {disconnect();  //关闭窗口的时候调用断开连接的方法System.exit(0);}});tfTex.addActionListener(new TFListener());this.setVisible(true);connect();tRecv.start();} /** * 6、与服务器建立连接Socket(主机,端口号) *  打印一句话作为测试 */public void connect() {try {s = new Socket("127.0.0.1",8888);dos = new DataOutputStream(s.getOutputStream());dis = new DataInputStream(s.getInputStream());System.out.println("connect");bConnected = true;} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}/** * 8.1、当连接断开的时候,关闭socket */public void disconnect() {try {bConnected = false;dos.close();dis.close();s.close();} catch (IOException e) {e.printStackTrace();}/*try {bConnected = false;tRecv.join();} catch (InterruptedException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {try {dos.close();dis.close();s.close();} catch (IOException e) {e.printStackTrace();}}*/}/** * 4、将输入框的内容显示到显示区域。这里使用内部类(方便修改以及添加内容,不被其它内调用) */private class TFListener implements ActionListener {@Overridepublic void actionPerformed(ActionEvent e) {String str = tfTex.getText().trim();  //得到输入框的内容//taContent.setText(str);  //显示到TextAreatfTex.setText("");   //将输入框的内容输出后,设置为空/** * 7.1、建立输出流,向服务器端写入内容 *    定义为成员变量,创建对象放到连接里,连接不断开就可以一直向服务器发送信息 */try {dos.writeUTF(str);dos.flush(); //添加冲刷/刷新} catch (IOException e1) {e1.printStackTrace();}}}/** * 12、启用线程接收服务器发送的信息 */public class RecvThread implements Runnable {@Overridepublic void run() {try{while(bConnected){String str = dis.readUTF();//System.out.println(str);taContent.setText(taContent.getText() + str +"\n");}} catch(SocketException e) {System.out.println("a client 已退出!");}catch(IOException e) {e.printStackTrace();}}}}