socket通過(guò)三次握手建立連接,通信完成時(shí)拆除連接
四要素是:客戶端地址,客戶端端口,服務(wù)端地址,服務(wù)端端口
客戶端和服務(wù)端的代碼編寫(xiě)
關(guān)于 Thread 類(lèi)(https://blog.csdn.net/qq_58266033/article/details/123638588)
在java標(biāo)準(zhǔn)庫(kù)中,提供了一個(gè)Thread類(lèi),用來(lái)表示/操作線程,Thread類(lèi)可以視為是Java標(biāo)準(zhǔn)庫(kù)提供的API,Java是支持多線程編程的,在Java中創(chuàng)建好的Thread實(shí)例,其實(shí)和操作系統(tǒng)中的線程是一一對(duì)應(yīng)的關(guān)系,操作系統(tǒng)提供了一組關(guān)于線程的API(C語(yǔ)言),Java對(duì)于這組API進(jìn)一步封裝之后就變成了Thread類(lèi)
最簡(jiǎn)單的創(chuàng)建線程方式 寫(xiě)一個(gè)類(lèi)繼承線程Thread類(lèi) 再重寫(xiě)run方法
服務(wù)端Server.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
// 新建一個(gè)服務(wù)器socket 只需要設(shè)置端口即可 不需要設(shè)置ip
ServerSocket server = new ServerSocket(2000);
System.out.println("服務(wù)器準(zhǔn)備就緒--");
System.out.println("服務(wù)器信息:"+server.getInetAddress()+" P:"+server.getLocalPort());
// 無(wú)限循環(huán) 接收來(lái)自客戶端的請(qǐng)求
for (;;){
// 接受客戶端 獲得客戶端的client信息
Socket client = server.accept();
// 握手接收到以后 開(kāi)一個(gè)線程執(zhí)行線程里面的操作
ClientHandler clientHandler = new ClientHandler(client);
// 線程執(zhí)行
clientHandler.start();
}
}
// 新建一個(gè)類(lèi) 繼承線程里面的方法
private static class ClientHandler extends Thread{
private Socket socket;
private boolean flag = true;
ClientHandler(Socket socket){
this.socket = socket;
}
//重寫(xiě)線程里面的run方法
@Override
public void run() {
// 先繼承原有run方法
super.run();
// 打印出客戶端的相關(guān)信息
System.out.println("新客戶端連接:"+socket.getInetAddress()+" P:"+socket.getPort());
try {
//得到打印流 用于數(shù)據(jù)輸出;服務(wù)器
//客戶端的輸出流 作為一個(gè)打印流
PrintStream socketOutput = new PrintStream(socket.getOutputStream());
//客戶端的輸入流 轉(zhuǎn)換為BufferedReader
BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));
do{
//客戶端拿到一條數(shù)據(jù)
//從打印流拿到數(shù)據(jù)
String str = socketInput.readLine();
if("bye".equalsIgnoreCase(str)){
flag=false;
socketOutput.println("bye");
}else {
System.out.println(str);
//輸出流往客戶端寫(xiě)東西
socketOutput.println("回送"+str.length());
}
}
while (flag);
}catch (Exception e){
System.out.println("連接異常斷開(kāi)");
}finally {
try {
socket.close();
}catch (IOException e){
e.printStackTrace();
}
}
System.out.println("客戶端已退出:"+socket.getInetAddress()+" P:"+socket.getPort());
}
}
}
客戶端Client.java
import java.io.*;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;
// 新建一個(gè)客戶端
public class Client {
// main函數(shù)
public static void main(String[] args) throws IOException {
// 新建一個(gè)socket
Socket socket = new Socket();
// 設(shè)置超時(shí)時(shí)間
socket.setSoTimeout(3000);
// 設(shè)置連接本地 端口2000;超時(shí)時(shí)間3000
socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(),2000),3000);
System.out.println("已發(fā)起服務(wù)器連接,并進(jìn)入后續(xù)流程--");
System.out.println("客戶端信息:"+socket.getLocalAddress()+" P:"+socket.getLocalPort());
System.out.println("服務(wù)器信息:"+socket.getInetAddress()+" P:"+socket.getPort());
//連接到服務(wù)器以后 做todo()方法的相關(guān)操作 傳入socket參數(shù)是為了得到服務(wù)器的輸入流和輸出流
try {
todo(socket);
}catch (Exception e){
System.out.println("異常關(guān)閉");
}
// 釋放資源
socket.close();
System.out.println("客戶端已退出");
}
public static void todo(Socket client) throws IOException {
// BufferedReader 從字符輸入流中讀取文本,緩沖各個(gè)字符,從而實(shí)現(xiàn)字符、數(shù)組和行的高效讀取。
// 構(gòu)建鍵盤(pán)輸入流
//將InputStreamReader轉(zhuǎn)為BufferedReader
InputStream inputStream= System.in;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
// 得到Client輸出流,并轉(zhuǎn)換為打印流
// outputStream 直接轉(zhuǎn)換為PrintStream 打印流
OutputStream outputStream = client.getOutputStream();
PrintStream socketPrintStream = new PrintStream(outputStream);
// 得到Client輸入流,并轉(zhuǎn)換為BufferedRead
InputStream inputStream1 = client.getInputStream();
BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(inputStream1));
boolean flag = true;
do {
//鍵盤(pán)讀取一行
String str = bufferedReader.readLine();
// 通過(guò)打印流發(fā)送到服務(wù)器
socketPrintStream.println(str);
//從服務(wù)器讀取一行
String echo = bufferedReader1.readLine();
// 如果是bye則不做操作 否則打印出來(lái)
if ("bye".equalsIgnoreCase(echo)) {
}else{
System.out.println(echo);
}
}
// 重復(fù)輸入 直到斷開(kāi)
while(flag);
//關(guān)閉socketPrintStream 釋放內(nèi)存
socketPrintStream.close();
}
}