网络编程-bio

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")获取当前项目的路径,多级目录间用"\"隔开

猜你喜欢

转载自blog.csdn.net/qq_42514129/article/details/86222786