java实现简单聊天程序(集合,线程,I/O,网络编程)

来源:互联网 发布:医药大数据 编辑:程序博客网 时间:2024/06/11 05:36

这半个月的大作业,程序有一些不完善的地方有待提高,但是基本的聊天室功能已经可以实现

还没有接触javaFx所以用了swing做了简陋的界面



补充:{

今天突然记起来,把这个大作业交了,然后大佬突然问我这个程序有没有线程安全问题,怎么处理的。
我以为这只是把socket传入的字节重新传到客户端不存在修改也不存在线程的安全问题,大佬说只要有多个线程共享的数据,就有可能有线程安全问题!!!切记
我恰好在服务器端用了vector集合存储了线程,所以避免了安全性问题,但是如果用了其他的容器还是会出现线程安全问题。
例如,ArrayList里,容量是有一个上限的,在当前容量已满的情况下,会进行扩容,先判断是否达到容量上限,如果没有,就将进行扩容,如果达到则会报异常。
如果没有给线程上锁,当有两个对象同时加入ArrayList里且容量只够再一次扩容时,会爆内存。
而使用vector则没有这种担忧,看过vector源码的API就会知道,vector的实现方法都用synchronized包装了。
synchronized:
这是java语言的关键字,被它修饰的方法或代码块在执行的时候能够保证在同一时刻最多只有一个线程执行该段代码,相当于一个上锁的操作。

}


截图:






客户端:

import java.awt.BorderLayout;import java.awt.Color;import java.awt.Container;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;import java.net.UnknownHostException;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JScrollPane;import javax.swing.JTextArea;import javax.swing.JTextField;public class Client extends JFrame {private static final long serialVersionUID = 1L;JTextField JTF = new JTextField();JTextArea JTA = new JTextArea();JScrollPane JSP = new JScrollPane(JTA);Socket socket = null;OutputStream ops = null;InputStream ips = null;    String name = new String();     public void makeWindow(){name = JOptionPane.showInputDialog(null, "请输入用户名字", "输入用户名", JOptionPane.INFORMATION_MESSAGE);     connect();JFrame frame = new JFrame("聊天窗口"); frame.setSize(500, 400);    Container contentPane = frame.getContentPane();    JPanel panel = new JPanel();    panel.setBackground(Color.CYAN);    JButton bts = new JButton("send");     JButton btc = new JButton("close");     panel.add(bts);    panel.add(btc);    JTA.setEditable(false);    JPanel panel_ = new JPanel(new BorderLayout());    panel_.add(JTF, BorderLayout.SOUTH);//    panel_.add(JTA, BorderLayout.CENTER);    panel_.add(JSP, BorderLayout.CENTER);    contentPane.add(panel, BorderLayout.SOUTH);    contentPane.add(panel_, BorderLayout.CENTER);    frame.setVisible(true);    frame.setLocationRelativeTo(null);    frame.addWindowListener(new WindowAdapter() {    public void windowClosing(WindowEvent e) {    CloseAll();    System.out.println("已关闭窗口");        System.exit(0);    }});    btc.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {CloseAll();System.out.println("press the btc");System.exit(0);}});    bts.addActionListener(new ButtonListener());new Thread(new ClientTest()).start();}public class ButtonListener implements ActionListener{public void actionPerformed(ActionEvent arg0) {String str = new String();str = JTF.getText();Date date = new Date();DateFormat format = new SimpleDateFormat("HH:mm:ss");String time = format.format(date);str = name + " send at " + time + ":\n" + str;JTF.setText("");try {ops.write(str.getBytes());} catch (IOException e) {e.printStackTrace();CloseAll();}}}public static void main(String[] args) {Client c = new Client();c.makeWindow();}public void connect(){try {socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);ops = socket.getOutputStream();System.out.println("Open the Socket");} catch (UnknownHostException e) {CloseAll();e.printStackTrace();} catch (IOException e) {CloseAll();e.printStackTrace();}}public void CloseAll(){if(ips != null){try {ips.close();} catch (IOException e) {e.printStackTrace();}}if(ops != null){try {ops.close();} catch (IOException e) {e.printStackTrace();}}if(socket != null){try {socket.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("Close All");}class ClientTest implements Runnable{@Overridepublic void run(){try {ips = socket.getInputStream();byte[] b = new byte[1024];int len;while((len = ips.read(b)) != -1){String receStr = new String(b, 0, len);String appear = new String();appear = JTA.getText()+ receStr + '\n';JTA.setText(appear);JTF.setText("");}} catch (IOException e) {System.out.println("I hava closed! Please don't send message!");}}}}



服务器端

import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.ServerSocket;import java.net.Socket;import java.util.Vector;public class Server {public Vector<ServerTest> v = new Vector<ServerTest>();ServerSocket ss = null;//Socket s = null;//InputStream ips = null;//OutputStream ops = null;public void receive(){try {ss = new ServerSocket(9090);System.out.println("I am the Server");} catch (IOException e1) {e1.printStackTrace();}try {while(true){Socket s = ss.accept();ServerTest st = new ServerTest(s);System.out.println("a client connected!");v.add(st);new Thread(st).start();}} catch (IOException e) {e.printStackTrace();}finally{if(ss != null){try {ss.close();} catch (IOException e) {e.printStackTrace();}}System.out.println("I have close all!");}}public static void main(String[] args) {Server server = new Server();server.receive();}class ServerTest implements Runnable{Socket s = null;InputStream ips = null;OutputStream ops = null;public ServerTest(Socket s){this.s = s;}public void run() {try {while(true){this.ips = this.s.getInputStream();this.ops = this.s.getOutputStream();byte[] b = new byte[1024];int len;while((len = this.ips.read(b)) != -1){String str = new String(b, 0, len);for(int i = 0; i < v.size(); i++){ServerTest st = v.get(i);st.ops.write(str.getBytes());}}}} catch (IOException e) {e.printStackTrace();}finally{if(ips != null){try {ips.close();} catch (IOException e) {e.printStackTrace();}}if(ops != null){try {ops.close();} catch (IOException e) {e.printStackTrace();}}if(s != null){try {s.close();} catch (IOException e) {e.printStackTrace();}}}}}}