ClientSocket
public class TestClient{
public static void main(String[] args){
Socket socket = null;
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 server = null;
Socket socket = null;
OutputStream os = null;
try{
server = new ServerSocket(8080);
while(true){
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 {
private static String WEB_ROOT = System.getProperty("user.dir") + "/network/src/main/webapp";
private static String url;
private static Map<String, File> webMap = new HashMap<String, File>();
public static void main(String[] args) {
WEB_ROOT = WEB_ROOT.replace("\\", "/");
ServerSocket server = null;
Socket socket = null;
InputStream is = null;
OutputStream os = null;
try {
server = new ServerSocket(8888);
while (true) {
socket = server.accept();
is = socket.getInputStream();
parseUrl(is);
os = socket.getOutputStream();
responseView(os);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
closeMethod(is);
closeMethod(os);
closeMethod(socket);
}
}
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 = WEB_ROOT + content.substring(index1, index2).trim();
System.out.println("url:" + url);
}
}
}
private static void responseView(OutputStream os) {
InputStream is = null;
try {
loadFile(new File(WEB_ROOT));
File file = webMap.get(url);
if (file == null) {
file = webMap.get(WEB_ROOT + "/404.html");
}
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);
}
}
private static void loadFile(File file) {
if (file != null && file.exists()) {
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")获取当前项目的路径,多级目录间用"\"隔开