1. 程式人生 > >使用多線程實現多個客戶端與服務端通信1

使用多線程實現多個客戶端與服務端通信1

runnable system 處理異常 封裝 端口被占用 直接 客戶端連接 i++ 應用程序

Server.java

package socket;

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 小明
*
*/
public class Server {
/**
* 運行在服務端的ServerSocket主要有兩個作用:
* 1:向系統申請服務端口,客戶端就是通過這個端口與服務端建立連接的。
* 2:監聽服務端口,一旦客戶端與服務端建立連接,就會
* 自動創建一個Socket,並通過該Socket與建立連接的
* 客戶端進行交互。
*
*/
private ServerSocket server;

public Server()
{
try{
/**
* 實例化ServerSocket的同時要指定向系統申請的服務端口。註意,該端口
* 不能與當前系統其它應用程序申請的端口號一致,
* 否則會拋出端口被占用的異常。
*/
System.out.println("正在啟動服務端...");
server = new ServerSocket(8088);
System.out.println("服務端啟動完畢!");
}catch(Exception e){

}
}

public void start()
{
try {
while(true)
{
System.out.println("等待客戶端連接");
Socket socket = server.accept();
//accept用來感知socket。
System.out.println("一個客戶端連接進去了。");

ClientHandler hander = new ClientHandler(socket);
Thread t1 = new Thread(hander);
t1.start();
}
/**
* 準備接受客戶端連接
*
* 這是一個阻塞方法。
*一旦調用accpet()方法,服務端阻塞在這裏,等著客戶端連接了。
*這時當我們啟動客戶端時,客戶端實例化socket,通過IP找到應用程序。
*這時accpet()馬上就會有反應。accpet()方法執行完就返回一個socket。
*通過這個socket就可以與剛建立連接的這個客戶端進行通訊了。
*客戶端創建一個socket,服務端通過accept()接收一個socket。
*這時候就可以進行溝通了。
* 需要處理異常。
*/
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public static void main(String[] args) {
Server server = new Server();
server.start();
}

/**
* 通過輸入流讀取遠端計算機發送過來的信息時
* br.readLine()方法對於不同系統的客戶端斷開時的反應不一樣
* windows的客戶端斷開時,會直接拋出異常
* linux的客戶端斷開時,會返回null
* 該線程任務是負責與指定的客戶端進行交互
* @author 小明
*
*/
private class ClientHandler implements Runnable{
private Socket socket;
private String host;
//創建時需要將Socket傳入,以便對該客戶端交互
public ClientHandler(Socket socket) {
this.socket = socket;
//通過socket獲取遠端的地址信息
InetAddress address = socket.getInetAddress();
host = address.getHostAddress();
}
@Override
public void run() {
try{
System.out.println("進入了線程,現在正在調用run()方法");
InputStream in = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
String message = null;
System.out.println("客戶端地址是:" + host);
//System.out.println("嘗試輸出br.readLine()" + br.readLine());
System.out.println("while最上面的那條語句");

while((message = br.readLine()) != null)
{
System.out.println("讀取到了數據");
System.out.println(host + "說" + message);
System.out.println("一個客戶端連接了");
}
if(message == null){
System.out.println("message是空的");
}
br.close();
}catch(IOException e){
e.printStackTrace();
}finally{
//br.close();
}
}

}

}

Client.java

package socket;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

/**
* 聊天室客戶端
* @author 小明
*
*/
public class Client {
/**
* 套接字
* 封裝了TCP協議的通信細節,讓我們可以簡單地使用它完成TCP通訊
* Socket連接後提供了兩條流,通過兩條流的讀寫操作完成與遠端計算機的數據連接
* 完成與遠端計算機的數據交換。
*/
private Socket socket;
public Scanner reader;
/**
* 用來初始化客戶端
*/
public Client()
{
try {
/**
* 實例化Socket時需要傳入兩個參數:
* 1:服務端的IP地址
* 2:服務端的端口號
* 通過IP地址可以找到服務端所在的計算機
* 通過端口可以找到運行在服務端計算機上的
* 服務端應用程序
* 註意,實例化Socket的過程就是連接的過程,若
* 連接失敗就會拋出異常。
*/
reader = new Scanner(System.in);

System.out.println("正在連接服務端...");
socket = new Socket("localhost", 8088);
System.out.println("與服務端建立連接!");

/**
* 有兩個參數,一個是IP地址,一個是端口號
*/
/**
* 所有應用程序在使用網絡的時候都要和操作系統申請一個網絡端口
*
*/
/**
* 異常要我們自己進行處理,不要拋出
*/
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

/**
* 寫程序時不要過度依賴main方法
* 客戶端開始工作的方法
*/
public void start()
{
try{
//socket.getOutputStream();
//打樁
//可以找到代碼錯的地方。
PrintWriter pw = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream())), true);
//pw.write("你好服務端");
//使用上面這條語句是錯的,要使用具有自動行刷新的方法
//不要再下意識地寫上面那條語句了
// for(int i = 0; i < 10; i++){
// pw.println("你好服務端!" + i);
// }
while(true)
{
String line = reader.nextLine();
pw.println(line);
}

}catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
Client client = new Client();
client.start();
}

}

使用多線程實現多個客戶端與服務端通信1