聊天室代碼(只能羣聊,2個2個聊沒想好.....)

聊天室小結:

查看ip地址:linux,/sbin/config
        Windows/ipconfig 


******************************************************************************************************

package day03;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
//聊天室的客戶端
public class Client {
//套接字, java.net.Socket封裝了TCP協議,使用它就可以基於TCP協議進行網絡通訊, Socket是運行在客戶端的
private Socket socket;
 //構造方法,用於初始化客戶端,實例化Socket的過程就是連接的過程,若遠程計算機沒有響應會拋出異常

 //實例化Socket的時候傳入兩個參數:1.服務端的地址:通過IP地址可以找到服務的那臺計算機

        2.服務端端口:通過端口可以找到服務端計算機上的服務端的應用程序

public Client() throws Exception{
System.out.println("正在連接服務端!");
socket=new Socket("localhost",8086);//ip,端口號(0~65535).
System.out.println("已經與服務端建立連接");
}
/啓動客戶端的方法
public void start(){
try {
Scanner scanner=new Scanner(System.in);
//現要求用戶輸入暱稱
String nickName=null;
while(true){
System.out.println("請輸入用戶名");
nickName=scanner.nextLine();
if(nickName.length()>0){
break;
}
System.out.println("輸入有誤!");
}
System.out.println("歡迎你"+nickName+"!開始聊天吧!");

/*
* Socket提供的方法:
* OutputStream getOutputStream
* 獲取一個字符輸出流,通過該流
* 寫出的數據會被髮送至遠端計算機
*/
OutputStream out=socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(out,"utf-8");
PrintWriter pw=new PrintWriter(osw,true);

//現在先將暱稱發送給服務端
pw.println(nickName);
//啓動讀取服務器發送過來的消息的線程
ServerHandler handler=new ServerHandler();
Thread t=new Thread(handler);
t.start();
while(true){
//將字符串發送至服務端
pw.println(scanner.nextLine());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args){
try {
Client client=new Client();
client.start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("客戶端啓動失敗!");
}
}
//該線程用於讀取服務端發送過來的消息並輸出到客戶端控制檯顯示
class ServerHandler implements Runnable{
public void run() {
try {
InputStream in=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(in,"utf-8");
BufferedReader br=new BufferedReader(isr);
String message=null;
while((message=br.readLine())!=null){
System.out.println(message);
}
} catch (Exception e) {

}
}
}

}

*********************************************************************************************************************************************************

package day03;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

//服務端
public class Server {
//運行在服務端的ServerSocket主要負責:
// 1.向系統申請服務端口,客戶端就是通過這個端口與之相連
// 2.監聽申請的服務端口,當一個客戶端通過該端口嘗試建立連接時,SreverSocket會在服務端創建一個Socket與客戶端建立連接
private ServerSocket server;
 //保存所有客戶端輸出流的集合
private List<PrintWriter> allOut;
//用來初始化服務端
public Server()throws Exception{
//初始化的同時申請服務端口 
server=new ServerSocket(8086);
allOut=new ArrayList<PrintWriter>();
}
//將給定的輸出流存入共享集合
private synchronized void addOut(PrintWriter out){
allOut.add(out);
}
//將給定的輸出流從共享集合中刪除
private synchronized void removeOut(PrintWriter out){
allOut.remove(out);
}
//將給定的消息發送給所有的客戶端
private synchronized void sendMessage(String message){
for(PrintWriter out :allOut){
out.println(message);
}
}
//服務端開始工作的方法
public void start(){
try {
/*
* ServerSocket的accept方法
* 是一個阻塞方法,作用是監聽
* 服務端口,直到一個客戶端連接並創建
* 一個Socket,使用該Socket
* 即可與剛連接的客戶端進行交互
*/
while(true){
System.out.println("等待客戶端連接...");
Socket socket=server.accept();
System.out.println("一個客戶端連接了!");
/*
* 啓動一個線程,來完成與該客戶端的交互
*/
ClientHandler handler=new ClientHandler(socket);
Thread t=new Thread(handler);
t.start();
}

} catch (Exception e) {

}

}
public static void main(String[] args) {
try {
Server server=new Server();
server.start();
} catch (Exception e) {
e.printStackTrace();
System.out.println("服務端啓動失敗!");
}
}

//該線程負責處理一個客戶端的交互
class ClientHandler implements Runnable{
//該線程處理的客戶端Socket
private Socket socket;
//客戶端的地址信息
private String host;
//該用戶的暱稱
private String nickName;
public ClientHandler(Socket socket){
this.socket=socket;
//通過Socket可以獲取遠端計算機的地址信息
InetAddress address=socket.getInetAddress();
//獲取ip地址
host=address.getHostAddress();
}
public void run(){
PrintWriter pw=null;
try {
/*
* Socket提供的方法
* InputStream getInputStream()
* 該方法可以獲取一個輸入流,從該流讀取的數據
* 就是從遠端計算機發送過來的
*/
InputStream in=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(in,"utf-8");
BufferedReader br=new BufferedReader(isr);

//首先讀取一行字符串爲暱稱
nickName=br.readLine();
sendMessage(nickName+"上線了!");
// 通過Socket創建輸出流用於將消息發送給客戶端
OutputStream out=socket.getOutputStream();
OutputStreamWriter osw=new OutputStreamWriter(out,"utf-8");
pw=new PrintWriter(osw,true);
 //將該客戶端的輸出流存入到共享集合
addOut(pw);
String message=null;
/*
* br.readLine()在讀取客戶端發送過來的消息時,
* 由於客戶端斷線,而其操作系統的不同,這裏讀取後的結果
* 不同:
* 當windows的客戶端斷開時:
* br.readLine會拋異常
* 當linux的客戶端斷開時
* br.readLine()會返回null
*/
while((message=br.readLine())!=null){
//System.out.println(host+"說:"+message);
//pw.println(host+"說:"+message);
sendMessage(nickName+"說:"+message);
}
} catch (Exception e) {

}finally{
//處理當前客戶端斷開後的邏輯
//將該客戶端的輸出流從共享集合中刪除
removeOut(pw);
sendMessage(nickName+"下線了!");
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章