java中一個服務端對客戶端的帶介面的聊天室
阿新 • • 發佈:2019-01-27
思路:用Swing包建立一個簡單的聊天的面板,實現與服務端的通訊,關鍵是將聊天面板傳送的Msg傳到服務端的Recieve執行緒中,將服務端Send執行緒中的Msg傳送到聊天面板中顯示,因此我選擇了用構造方法傳參的形式(其實也可以使用static方式)線上程中傳入Msg
這段程式碼只能實現一個服務端同一時間跟多個客戶端中的一個聊天,不能實現一個服務端同時跟多個客戶端進行群聊
服務端程式碼:
/**
* 實現多個客戶端對應一個服務端進行通訊
*
* @author wangjue
*
*/
public class MyServer {
public static void main(String[] args) {
MyServer ms = new MyServer();
ms.initServer(10010);
}
public void initServer(int port) {
try {
ServerSocket server = new ServerSocket(port);
System.out.println("服務端正等待客戶端連線...");
// 表示可以連線多個客戶端
while (true ) {
Socket socket = server.accept();
System.out.println("已經有一個客戶端連線上來了...");
// 啟動發訊息的執行緒
new Thread(new SendThread(socket)).start();
//啟動收訊息的執行緒
new Thread(new RecieveThread(socket)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 接收客戶端不斷傳來訊息的執行緒
*
* @author wangjue
*
*/
public class RecieveThread implements Runnable {
private Socket socket;
public RecieveThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
InputStream ips = socket.getInputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while (true) {
int t = ips.read();
// 收到換行符為止
while (t != '\n') {
bos.write(t);
t = ips.read();
}
byte[] b = bos.toByteArray();
String recieveMsg = new String(b);
System.out.println(recieveMsg);
bos.reset();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 傳送給客戶端的執行緒
*/
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;
import java.util.Scanner;
public class SendThread implements Runnable{
private Socket socket;
public SendThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
OutputStream ops = socket.getOutputStream();
while(true) {
Scanner sc = new Scanner(System.in);
String msg = "服務端說:"+sc.nextLine()+"----"+new Date(System.currentTimeMillis())+"\n";
ops.write(msg.getBytes());
ops.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
客戶端
public class MyClient {
public static void main(String[] args) {
MyClient mc = new MyClient();
mc.initClient("127.0.0.1", 10010);
}
public void initClient(String host, int port) {
try {
Socket socket = new Socket(host, port);
talkUI ui = new talkUI();
ui.initUI();
// 啟動收訊息的執行緒
RecieveThread rt = new RecieveThread(socket, ui);
new Thread(rt).start();
// 啟動發訊息的執行緒
SendThread st = new SendThread(socket, ui);
new Thread(st).start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 聊天面板
* @author wangjue
*
*/
public class talkUI implements ActionListener{
private JTextArea area1 = new JTextArea(15,30);
private JTextArea area2 = new JTextArea(10,30);
public OutputStream ops;
//在對話方塊輸入的內容
private String sendMsg;
//傳給服務端的內容
public String sendMsg2;
public JTextArea getArea1() {
return area1;
}
public void initUI() {
JFrame jf = new JFrame();
jf.setTitle("私人聊天室");
jf.setSize(400,600);
FlowLayout layout = new FlowLayout();
jf.setLayout(layout);
//顯示面板
area1.setEditable(false);
jf.add(area1);
//輸入面板
jf.add(area2);
//傳送按鈕
JButton btn = new JButton("傳送");
jf.add(btn);
jf.setDefaultCloseOperation(3);
jf.setVisible(true);
btn.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
sendMsg = area2.getText();
sendMsg2 = sendMsg+"\n"; //傳給服務端的訊息要加入換行符,服務端才能知道什麼時候結束接收
//輸入的內容要顯示在面板上
area1.append("自己說:"+sendMsg+"----"+new Date(System.currentTimeMillis())+"\n");
//點擊發送後,輸入面板要清空
area2.setText("");
//要每點選一次傳送就要將內容寫入輸出流中
try {
ops.write(sendMsg2.getBytes());
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
/**
* 接收服務端傳來的訊息並顯示在面板上
* @author wangjue
*
*/
public class RecieveThread implements Runnable {
private Socket socket;
private talkUI ui;//傳入面板物件,呼叫getArea1方法獲取area1物件
public RecieveThread(Socket socket,talkUI ui) {
this.socket = socket;
this.ui = ui;
}
@Override
public void run() {
try {
InputStream ips = socket.getInputStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while (true) {
int t = ips.read();
while (t != '\n') {
bos.write(t);
t = ips.read();
}
byte[] b = bos.toByteArray();
//收到服務端傳來的訊息
String msg = new String(b);
//將訊息顯示在訊息面板上
ui.getArea1().append(msg+"\n");
//將服務端的訊息接收到並顯示在面板後,清空輸入流,下次收到訊息後就不會顯示上次已經收到的訊息
bos.reset();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 向服務端傳送訊息
* @author wangjue
*
*/
public class SendThread implements Runnable {
private Socket socket;
private talkUI ui; //傳入ui物件,呼叫傳給服務端的訊息
public SendThread(Socket socket, talkUI ui) {
this.socket = socket;
this.ui = ui;
}
@Override
public void run() {
try {
ui.ops = socket.getOutputStream();
while (true) {
if(ui.sendMsg2!=null){
byte[] b = ui.sendMsg2.getBytes();
ui.ops.write(b);
ui.ops.flush();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
結果顯示: