網路程式設計-bio
阿新 • • 發佈:2019-01-11
ClientSocket
public class TestClient{
public static void main(String[] args){
//建議一個Socket連線
Socket socket = null;
//通過socket連線,輸出流(請求)物件,獲取輸入流(響應)
InputStream is = null;
OutputStream os = null;
try{
socket = new Socket("localhost",8080 );
//傳送請求
os = socket.getOutputStream();
os.write("GET localhost:8080 HTTP/1.1\n".getBytes()); //請求行
os.write("HOST:localhost:8080\n".getBytes()); //請求頭
os.write("\n".getBytes()); //請求空行
System.out.println("傳送請求,同步阻塞等待響應...");
//響應結果
is = socket.getInputStream();
int len;
while((len = is.read())!=-1){
System.out.print((char)len);
}
System.out.println("請求響應完畢,釋放資源...");
}catch(IOException e){
e.printStackTrace();
}finally{
//釋放資源
...
}
}
}
ServerSocket
public class TestServer{
public void main(String[] args){
//建立ServerSocket伺服器,並監聽8080埠
ServerSocket server = null;
Socket socket = null;
OutputStream os = null;
try{
server = new ServerSocket(8080);
while(true){
//server接收到有socket連線時,自動建立socket
socket = server.accept();
//獲取輸出流物件
os = socket.getOutputStream();
//響應資料
os.write("HTTP/1.1 200 OK\n".getBytes()); //響應行
os.write("Content-Type:text/html;charset=utf-8\n".getBytes()); //響應頭
os.write("\n".getBytes()); //響應空行
os.write(("<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Title</title>\n" +
"</head>\n" +
"<body>\n" +
" <h1>Response Success...</h1>\n" +
"</body>\n" +
"</html>").getBytes()); //響應體
}
}catch(IOException e){
e.printStackTrace();
}finally{
//釋放資源
...
}
}
}
}
TomcatServer
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class MyTomcatServer {
//web資源目錄
private static String WEB_ROOT = System.getProperty("user.dir") + "/network/src/main/webapp";
//使用者請求url
private static String url;
//儲存檔案集合
private static Map<String, File> webMap = new HashMap<String, File>();
public static void main(String[] args) {
//將WEB_ROOT中路徑反斜槓轉換成正斜槓
WEB_ROOT = WEB_ROOT.replace("\\", "/");
//建立ServerSocket伺服器,並監聽8080埠
ServerSocket server = null;
Socket socket = null;
InputStream is = null;
OutputStream os = null;
try {
server = new ServerSocket(8888);
while (true) {
//server接收到有socket連線時,自動建立socket
socket = server.accept();
//獲取輸入流物件(獲取請求引數)
is = socket.getInputStream();
//解析得到請求url
parseUrl(is);
//獲取輸出流物件(響應結果)
os = socket.getOutputStream();
//根據請求url響應檢視
responseView(os);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
closeMethod(is);
closeMethod(os);
closeMethod(socket);
}
}
//解析得到請求url
private static void parseUrl(InputStream is) throws IOException {
byte[] buff = new byte[2048];
int len = is.read(buff);
String content = new String(buff, 0, len);
System.out.println("content:" + content);
//對請求引數處理
int index1, index2;
index1 = content.indexOf(" ");
if (index1 != -1) {
index2 = content.indexOf(" ", index1 + 1);
if (index2 > index1) {
//找到了請求行中的url索引
url = WEB_ROOT + content.substring(index1, index2).trim();
System.out.println("url:" + url);
}
}
}
//根據請求url響應檢視
private static void responseView(OutputStream os) {
InputStream is = null;
try {
//讀取web目錄下的所有資源
loadFile(new File(WEB_ROOT));
File file = webMap.get(url);
if (file == null) {
//說明使用者輸入url沒有匹配的靜態網頁,返回404
file = webMap.get(WEB_ROOT + "/404.html");
}
//讀取file
is = new FileInputStream(file);
byte[] buff = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
String str = "";
while ((len = is.read(buff)) != -1) {
str = new String(buff, 0, len);
sb.append(str);
}
String content = sb.toString();
os.write("HTTP/1.1 200 OK\n".getBytes()); //響應行
os.write("Content-Type:text/html;charset=utf-8\n".getBytes()); //響應頭
os.write("\n".getBytes()); //響應空行
os.write(content.getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
closeMethod(is);
}
}
//將WEB_ROOT下的所有資源讀取到map中
private static void loadFile(File file) {
if (file != null && file.exists()) {
//檔案就存到map,資料夾就開啟
if (file.isFile()) {
//判斷是不是靜態網頁
String filename = file.getName();
if (filename != null && filename.contains("html")) {
String absolutePath = file.getAbsolutePath().replace("\\", "/");
webMap.put(absolutePath, file);
}
} else {
//資料夾則開啟資料夾
File[] listFiles = file.listFiles();
for (File fileSon : listFiles) {
loadFile(fileSon);
}
}
}
}
//釋放資源的方法
private static void closeMethod(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
TomcatServer原理
1.tomcat原理
ServerSocket類是tomcat的基石,當tomcat伺服器啟動,底層就啟動了ServerSocket,並且監聽8080埠,即ServerSocket server = new ServerSocket(8080);當瀏覽器端傳送請求,實際上是建立了一次Socket連線,ServerSocket監聽到這一次連線後,便在伺服器端接收連線;通過socket.getInputStream()獲取請求引數,再通過socket.getOutputStream()相應資料給瀏覽器端;
2.Socket通訊中read()方法阻塞問題:
is.read()返回-1的底層實現方式是:當讀取磁碟檔案時,輸入流讀取到檔案結束符,輸入流便知道檔案讀取完畢,返回-1;而網路傳輸中,輸入流並不知道什麼時候才能讀取完畢,因此會出現阻塞
三種解決解決方案:
* 用一個大的位元組陣列接收,避免while()迴圈
byte[] buff = new byte[2048];
int len = is.read(buff);
String str = new String(buff,0,len);
* 客戶端傳輸完畢後,手動關閉流
socket.shutdownOutput();
* 設定超時時間
socket.setSoTimeout(3000);
3.System.getProperty("user.dir")獲取當前專案的路徑,多級目錄間用"\"隔開