java 實現即時聊天設計(利用ip進行遠端通訊)
阿新 • • 發佈:2019-02-01
先看下效果圖,一端執行在遠端伺服器,一端在本機電腦上執行,在區域網內兩端可正常通訊,由於我學校網路是區域網,所以外網ip接收得到訊息,反之外網發訊息過來本機收不到。不是區域網的同學理論上可以直接通訊。
思路是利用Socket來收發資料。具體可看程式碼。
程式碼分為兩部分,一部分為聊天視窗的繪製,一部分為事件和通訊的實現,這裡一起貼了出來:
import java.awt.Button; import java.awt.Color; import java.awt.Font; import java.awt.Frame; import java.awt.Label; 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.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.util.Calendar; import javax.swing.JOptionPane; public class Chat { public static void main(String[] args) { new MyFrame(); new MyEvent(); Thread thread = new Thread(new MyRecevier()); thread.start(); } } class MySend { public MySend() throws Exception { DatagramSocket dSocket = new DatagramSocket(10000); Calendar c = Calendar.getInstance(); byte[] buf = ("from IP:" + InetAddress.getLocalHost() + "\r\n" + MyEvent.myText) .getBytes(); System.out.println("收到內容:" + MyEvent.myText); DatagramPacket dPacket = new DatagramPacket(buf, buf.length, InetAddress.getByName(MyEvent.myIp), 8888);// 自定義 // // DatagramPacket dPacket= // new DatagramPacket(buf, // buf.length,InetAddress.getByName("192.168.56.1"),8888);//本機測試 dSocket.send(dPacket); dSocket.close(); // 顯示自己發的資訊 // ----------------本機顯示測試------------------// String date = "Time:" + c.get(Calendar.YEAR) + "年" + (c.get(Calendar.MONTH) + 1) + "月" + c.get(Calendar.DAY_OF_MONTH) + "日" + c.get(Calendar.HOUR) + "時" + c.get(Calendar.MINUTE) + "分"; MyFrame.receField.append(date + "\r\nME:" + MyEvent.myText + "\r\n"); // MyFrame.receField.setText(date+"\r\n"+string); // ----------------本機測試------------------// // System.out.println(dPacket); } } class MyRecevier implements Runnable { Calendar c; public MyRecevier() { c = Calendar.getInstance(); } @Override public void run() { DatagramSocket dSocket = null; try { dSocket = new DatagramSocket(8888); } catch (SocketException e1) { e1.printStackTrace(); } ; byte[] buf = new byte[1024]; DatagramPacket dPacket = new DatagramPacket(buf, buf.length); while (true) { try { dSocket.receive(dPacket); } catch (IOException e) { e.printStackTrace(); } String string = new String(dPacket.getData(), 0, dPacket.getLength()); // ----------------本機顯示測試------------------// String date = "Time:" + c.get(Calendar.YEAR) + "年" + (c.get(Calendar.MONTH) + 1) + "月" + c.get(Calendar.DAY_OF_MONTH) + "日" + c.get(Calendar.HOUR) + "時" + c.get(Calendar.MINUTE) + "分"; MyFrame.receField.append(date + "\r\n" + string + "\r\n"); // MyFrame.receField.setText(date+"\r\n"+string); // ----------------本機測試------------------// } // dSocket.close(); } } class MyEvent { static String myIp = ""; static String myText; String myReceText; public MyEvent() { // 提交 MyFrame.btnPost.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { myIp = MyFrame.ipField.getText().toString().trim(); String[] strings = myIp.split("\\."); boolean t = true; if (strings.length != 4) { t = false; JOptionPane.showMessageDialog(null, "請輸入正確的IP地址!"); } else { for (int i = 0; i < strings.length; i++) { // 告知此字串是否匹配給定的正則表示式。 if (!strings[i] .matches("^[-+]?(([0-9]+)([.]([0-9]+))?|([.]([0-9]+))?)$")) { t = false; JOptionPane.showMessageDialog(null, "帶有非數字字元!"); break; } else if (Integer.parseInt(strings[i]) > 255 || Integer.parseInt(strings[i]) < 0) { t = false; JOptionPane.showMessageDialog(null, "請輸入正確的IP地址!"); break; } } } if (t) { myIp = MyFrame.ipField.getText().toString().trim(); System.out.println("目標IP:" + myIp); JOptionPane.showMessageDialog(null, "提交成功!"); } } }); // 清除 MyFrame.btnCancel.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { MyFrame.inputField.setText(" "); } }); // 傳送並清除編輯內容 MyFrame.btnSend.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { myText = MyFrame.inputField.getText().toString().trim(); if (myIp.equals("")) { JOptionPane.showMessageDialog(null, "請輸入目標IP並提交!"); } else if (myText.equals("")) { JOptionPane.showMessageDialog(null, "請輸入內容再發送!"); } else { System.out.println("傳送內容:" + myText); MyFrame.inputField.setText(" "); try { new MySend(); } catch (Exception e1) { e1.printStackTrace(); } } } }); // 重新整理聊天記錄 MyFrame.btnRecord.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub } }); } } class MyFrame { Frame frame; static Button btnSend, btnRecord, btnCancel, btnPost; static TextArea inputField, recordField, receField; static TextField ipField; MyFrame() { frame = new Frame("IP聊天"); frame.setSize(432, 500); frame.setLayout(null); frame.setLocation(400, 150); frame.setResizable(false); frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.setVisible(true); frame.setBackground(Color.gray); InputFrame(); } public void InputFrame() { Label label1 = new Label(); Label label2 = new Label("輸入IP並提交:"); label1.setBounds(5, 10, 460, 200); label2.setBounds(8, 465, 80, 30); ipField = new TextField(); ipField.setBounds(85, 467, 148, 25); inputField = new TextArea("", 5, 10, TextArea.SCROLLBARS_VERTICAL_ONLY); recordField = new TextArea("", 5, 10, TextArea.SCROLLBARS_NONE); receField = new TextArea("", 5, 10, TextArea.SCROLLBARS_VERTICAL_ONLY); inputField.setBounds(5, 320, 420, 140); inputField.setBackground(Color.cyan); recordField.setBounds(430, 30, 165, 430); recordField.setBackground(Color.cyan); receField.setBounds(5, 30, 420, 285); receField.setBackground(Color.cyan); inputField.setFocusable(true); receField.setFocusable(false); recordField.setFocusable(false); ipField.setFont(new Font("Monospaced", Font.BOLD, 15)); inputField.setFont(new Font("Monospaced", Font.BOLD, 25)); receField.setFont(new Font("Monospaced", Font.BOLD, 18)); recordField.setFont(new Font("Monospaced", Font.BOLD, 15)); btnCancel = new Button("取消"); btnSend = new Button("傳送"); btnRecord = new Button("重新整理紀錄"); btnPost = new Button("提交"); btnCancel.setBounds(295, 465, 60, 30); btnSend.setBounds(360, 465, 60, 30); btnRecord.setBounds(435, 465, 80, 30); btnPost.setBounds(240, 465, 50, 30); frame.add(inputField); // frame.add(recordField); frame.add(receField); frame.add(btnCancel); frame.add(btnSend); // frame.add(btnRecord); frame.add(btnPost); frame.add(label1); frame.add(label2); frame.add(ipField); } }