ServerSocket
具體用法參考jdk:
http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4
爲了方便理解ServerSocket
服務器與客戶端的關係以及數據的交換
請看下圖:
下面直接演示ServerSocket實現的幾個功能:
一、 客戶端服務端發信息給服務端
二、模擬一個廣播電臺(服務端向客服端發送信息)
三、模擬一個對講機(半雙工模式)只能交替通話,不能同時通話
四、做一個木馬文件
五、客戶端發送一個命令到服務端,服務端接收之後,在服務器執行這個命令,並把執行的結果返回給客戶端
示例中所用到的java包:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
一、 客戶端服務端發信息給服務端
/**
* ServerSocket 實現服務端與客戶端通訊
*
* @author PeicongHe
*
*/
public class ServerSocketDemo {
/**
* 步驟:
* 1 先創建一個服務端,端口號爲:8888
* 2 等待客戶端連接
* 3 創建一個客戶端的輸入流(用於將信息發送給服務端)
* 4 服務端打印並顯示信息
*/
public static void test1() {
try {
ServerSocket serverSocket = new ServerSocket(8888); // 創建一個服務端,監聽端口8888
Socket socket = serverSocket.accept(); // 等待客戶端連接過來
System.out.println("來客IP: " + socket.getInetAddress()); // 獲取來客的IP地址
InputStream is = socket.getInputStream();// 客戶端的輸入流
Scanner sc = new Scanner(is);
String msg = "";
while (sc.hasNextLine()) {
msg = sc.nextLine();
System.out.println(msg);
if (msg.equals("exit")) {
System.out.println("我要退出!");
System.exit(0);
}
}
sc.close();
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Static void main(String[] args){
test1();
}
}
/**
* 增加自動回覆功能
* 步驟:
* 1 在獲取客戶端輸入流前添加一個客戶端輸出流(用於輸出自動回覆內容)
* 2 打印輸出流信息
* 3 刷新打印
*/
public static void test2() {
try {
ServerSocket serverSocket = new ServerSocket(8888);
Socket socket = serverSocket.accept();
System.out.println("來客ip: " + socket.getInetAddress());
// 增加一個自動回覆
OutputStream os = socket.getOutputStream();// 添加一個客戶端輸出
PrintWriter pw = new PrintWriter(os);// 打印出來
pw.print("welcome to my home!");// 打印的信息
pw.flush();// 刷新打印
InputStream is = socket.getInputStream();
Scanner sc = new Scanner(is);
String msg = "";
while (sc.hasNextLine()) {
msg = sc.nextLine();
System.out.println(msg);
if (msg.equals("exit")) {
System.out.println("再見!我要退出!");
System.exit(0);
}
}
sc.close();
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
二、模擬一個廣播電臺(服務端向客服端發送信息)
/**
* 模擬一個廣播電臺,特點是隻能服務端說話,不能客戶端說話
* 步驟:
* 1 創建一個服務端
* 2 接收一個客戶端
* 3 創建一個服務端的輸入流(用於存儲系統輸入的數據流)
* 4 創建一個客服的輸出流(用於在客服上顯示出數據)
* 5 掃描打印,刷新打印
*/
public static void broadcast(){
try {
ServerSocket server = new ServerSocket(8888);// 創建一個服務端,監聽端口8888
Socket socket = server.accept();// 等待客戶端連接過來
System.out.println("Ip: "+socket.getLocalAddress()+" 成功接入! ");
OutputStream serverops1 = socket.getOutputStream();// 獲取來客的IP地址
//自動回覆
PrintWriter pw1 = new PrintWriter(serverops1);
pw1.write("歡迎接入服務器!");
pw1.flush();
InputStream serverips = System.in;//在服務端輸入廣播內容做爲輸入流
OutputStream serverops2 = socket.getOutputStream();//輸出流用於傳輸信息給客戶端
PrintWriter pw = new PrintWriter(serverops2);
//獲取信息
Scanner sc = new Scanner(serverips);
String msg="";
while(sc.hasNextLine()){
msg = sc.nextLine();
pw.println(msg);//輸出信息
pw.flush();
if(msg.equals("exit")){
System.out.println("服務端講話完畢,再見!");
System.exit(0);
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
三、模擬一個對講機(半雙工模式)只能交替通話,不能同時通話
/**
* 步驟:
* 1 創建服務端
* 2 接收一個客戶端
* 3 創建一個服務端的輸入流(用於在服務端輸入)
* 4 創建一個客戶端的輸出流(用於在客戶端顯示)
* 5 創建一個客戶端的輸入流 (用於在服務端顯示)
* 6 獲取客戶端發送的信息
* 7 每次客戶端輸入一段話過來,我們都要從鍵盤輸入一段話,並且發送給客戶端
*/
public static void connunication(){
try {
ServerSocket server = new ServerSocket(8888);// 創建一個服務端,監聽端口8888
Socket socket = server.accept();//接收一個客戶端
Scanner scannerSystemIn = new Scanner(System.in);//創建一個服務端的輸入流(用於在服務端輸入)
PrintWriter pw = new PrintWriter(socket.getOutputStream());//創建一個客戶端的輸出流(用於在客戶端顯示)
Scanner scanner =new Scanner(socket.getInputStream());//創建一個客戶端的輸入流 (用於在服務端顯示)
String msg = "";
String serverMsg ="";
while(scanner.hasNextLine()){//獲取客戶端發送的信息
msg=scanner.nextLine();
System.out.println("客戶端的輸入: "+msg);
//當輸入exit 退出循環,結束通信
if(msg.equals("exit")||serverMsg.equals("exit")){
System.out.println("退出連接!");
System.exit(0);
}
//每次客戶端輸入一段話過來,我們都要從鍵盤輸入一段話,並且發送給客戶端
if(scannerSystemIn.hasNextLine()){
serverMsg = scannerSystemIn.nextLine();
System.out.println("服務端輸入: " + serverMsg);
pw.println("服務端說:"+serverMsg);
pw.flush();
}
}
//關閉流
pw.close();
scannerSystemIn.close();
scanner.close();
} catch (IOException e) {
e.printStackTrace();
}
四、做一個木馬文件
/**
* 客戶端可以通過輸入一個文件名傳給服務端,服務端就會根據文件的地址,將文件的內容返回給客戶端
*/
public static void test5() {
try {
// 1:創建一個服務端,監聽一個端口
ServerSocket serverSocket = new ServerSocket(8888);
// 2:獲取一個客戶端對象
Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
Scanner scanner = new Scanner(is);
PrintWriter pw = new PrintWriter(socket.getOutputStream());
while (scanner.hasNextLine()) {
// 3 接受客戶端的一個文件名
String fileName = scanner.nextLine();
// 4:讀取文件
String content = getContentFromFile(fileName);
// 5:把文件內容返回給客戶端
pw.println(content);
pw.flush();
}
is.close();
socket.close();
pw.close();
// 4:
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
五、客戶端發送一個命令到服務端,服務端接收之後,在服務器執行這個命令,並把執行的結果返回給客戶端
/**
* 功能: 客戶端發送命令控制服務端,服務端返回執行結果給客戶端
* 步驟:
* 1、獲取客戶端發送給服務端的命令
* 2、服務器運用進程的語句執行命令,保存執行的結果
* 3、判斷執行結果
* 4、將執行的結果發送給客戶端
*/
public static void test() {
try {
ServerSocket server = new ServerSocket(8888);
// 由於我們平時測試的時候,每次出錯或者每次在客戶端斷開連接的時候,服務端都會自動斷開
// 爲了解決這個問題,我們寫了一個循環,當一個連接退出時,服務端自動進入下一個連接
while (true) {
Socket socket = server.accept();
Scanner scanner = new Scanner(socket.getInputStream());
PrintWriter pw = new PrintWriter(socket.getOutputStream());
String command = "";
String p1Content = "";
String p2Content = "";
// String p1go = "";
while (scanner.hasNextLine()) {
command = scanner.nextLine();
Process p = Runtime.getRuntime().exec(command);
// 需要從進程執行後的結果中得到一個輸入流,這裏我們想要的信息
Scanner p1go = new Scanner(p.getInputStream());
while (p1go.hasNextLine()) {// 輸出到客戶端
p1Content = p1go.nextLine();
pw.println(p1Content);
pw.flush();
}
// 如果命令執行錯誤,就會有一個錯誤流
Scanner p2er = new Scanner(p.getErrorStream());
while (p2er.hasNextLine()) {
p2Content = p2er.nextLine();
}
// 如果錯誤流不爲空,就把錯誤信息輸出到客戶端
if (!p2Content.equals("")) {
pw.print(p2Content);
pw.flush();
}
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}