1. 程式人生 > >java 實現即時聊天設計(利用ip進行遠端通訊)

java 實現即時聊天設計(利用ip進行遠端通訊)

先看下效果圖,一端執行在遠端伺服器,一端在本機電腦上執行,在區域網內兩端可正常通訊,由於我學校網路是區域網,所以外網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);

	}

}