一個簡單的消息羣裏的聊天室功能,雖然功能不強大,主要是爲了給初學者梳理梳理一下思路。希望能夠幫到有需要的人,大家一同共同學習,互相幫助。’
package mysocket;
import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
/**
* 客戶端
* @author DELL
*
*/
public class Client {
/*
* Socket 套接字
* 封裝了TCP協議連接和通訊的細節,使用它與遠端計算檢疫連接後可以通過兩條流來實現
* 相互的數據交換
*/
private Socket socket;
//主方法
public static void main(String[] args) {
Client client = new Client();
client.start();
}
//構造方法,初始化程序
public Client() {
/*
* 實例化Socket
* 實例Socket需要傳入兩個參數
* Socket(String host, int port)
* 1:服務端計算機地址信息(IP)
* 2:服務端程序申請的服務端口
*
* 實例化過程就是與服務端建立連接的過程,
* 若指定的IP地址與端口無效時,這裏實例化
* 就會拋出異常。因此我們在實例化的同時要處理
* 異常。
*
*/
try {
System.out.println("正在連接服務端...");
socket = new Socket("localhost",8088);
System.out.println("服務端連接成功!");
} catch (Exception e) {
}
}
//運行程序的方法
public void start() {
/*
* 這裏執行與服務端進行消息交互的方法。
* 如果希望向服務端發送消息我們需要通過Socket
* OutputStream getOnputStream()
* 方法獲取輸出流
*/
try {
/*
* 串聯一個流連接,提升效率
*/
OutputStream out = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(out,"UTF-8");
BufferedWriter bw = new BufferedWriter(osw);
PrintWriter pw = new PrintWriter(bw,true);//此處注意參數true,若不添加此方法我們需要頻繁調用flush方法來保證消息的及時性。
Scanner scan = new Scanner(System.in);
while(true) {
String line = scan.nextLine();
pw.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package mysocket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服務端
* @author DELL
*
*/
public class Server {
/*
* java.net.ServerSocket
* 運行在服務端的ServerSocket主要有兩個作用
* 1:向系統申請服務端口,客戶端就是通過這個端口與服務端建立連接的
* 2:監聽服務端口,一旦客戶端通過該端口連接則馬上會實例化一個
* Socket與之反應。服務端就可以通過這個Socket與客戶端進行交互了。
*
* 如果把Socket比喻爲電話,那麼ServerSocket可以想象爲是總機。
*/
private ServerSocket server;
public static void main(String[] args) {
Server server = new Server();
server.start();
}
//構造方法,初始化程序
public Server() {
try {
/*
* 實例化ServerSocket的同時要制定服務端口。
* 當該端口已經被系統其它程序所使用時,會拋出地址被佔用的異常。
* 因此我們也需要使用異常處理機制處理一下。
*/
System.out.println("正在啓動服務端...");
server = new ServerSocket(8088);
System.out.println("服務端啓動完畢!");
} catch (IOException e) {
}
}
public void start() {
while(true) {
/*
* ServerSocket提供的方法:
* Socket accept();
* 該方法是一個阻塞方法,執行後服務端開始監聽服務端口,知道一個客戶端連接爲止,
* 這時該方法會返回一個Socket實例,通過該實例即可以與客戶端進行通訊了。
* 每次調用該方法都會導致服務端阻塞,等待一個客戶端的連接。
*/
try {
System.out.println("正在等待客戶端連接...");
Socket socket = server.accept();
//此時在等待一個窗口爲8088的客戶端連接,我們要實現羣聊效果,因此需要使用到多線程。
MyRunnable client = new MyRunnable(socket);
Thread thread = new Thread(client);
thread.start();
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
class MyRunnable implements Runnable{
private Socket socket;
String host;
public MyRunnable(Socket socket) {
this.socket = socket;
/*
* getInetAddress()返回對象包含遠程計算機的IP地址
* InetAddress.getHostAddress()返回對象與該地址的文本表示。
*/
InetAddress address = socket.getInetAddress();
host = address.getHostAddress();
System.out.println("IP:"+host+"連接成功!");
}
public void run() {
try {
//在這裏我也同樣通過Socket提供的方法實現與客戶端的交互
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in,"utf-8");
BufferedReader br = new BufferedReader(isr);
String str = null;
/*
* br.readLine()讀取客戶端發送過來的一行字符串的操作中
* 當客戶端斷開連接時,客戶端系統不同
* 這裏的表現也不同
* 通常windows的客戶端斷開時,readLine方法會直接拋出異常
* linux的客戶端斷開連接時,readLine方法的返回值通常爲null
*/
while((str = br.readLine())!=null) {
System.out.println("IP:"+host+"說:"+str);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}