这个是老师上课讲的,讲完之后感觉很神奇,后来我仔细看了TCP/IP我才发现其实Socket和Tcp/ip差不多,是自己没搞懂。 这科还挂了。。。真心很好,我有机会再学习一下。
先在项目下新建一个文件夹webapp,仿照tomcat
在这个文件夹下放俩个静态网站项目。随便
public class YcTomcat {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(9000);
while (true) {
Socket s = ss.accept();
System.out.println("一个socket对象进来了");
Thread t = new Thread(new TomcatService(s));
t.start();
}
}
}
/*
在浏览器中输入地址,然后浏览器给你拼接好一段基于http协议的数据包,然后通过DNS发送到主机。
服务器通过数据包中数据找到指定的文件,并返回流给客户端
*/
public class TomcatService implements Runnable {
private Socket s;
private InputStream iis; //输入流
private OutputStream oos; //输出流
private Scanner in; //输入
private PrintWriter out; //输出
/**
* 在构造方法中把流什么的先定义好
* @param s
*/
public TomcatService(Socket s){
try {
this.iis=s.getInputStream();
this.oos=s.getOutputStream();
in=new Scanner(iis);
out=new PrintWriter(oos);
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
//从输入流中读取协议的请求头,解析出请求的资源的地址 => Request对象
YcRequest request=new YcRequest(in);
String address=request.parse();
//根据这个地址以流的方式读取这个文件
String htmlContent=readHtmlFile(address);
//将这个文件的内容以输出流的形式传给客户端 => Response对象
YcResponse response=new YcResponse(out);
response.writeToClient(htmlContent);
}
/**
* 通过地址来获取一个html文件字符串代码
* @param address
* @return
*/
private String readHtmlFile(String address) {
StringBuffer htmlContent=new StringBuffer("");
String projectPath=getClass().getResource("/").getFile().toString();
// /C:/Users/suibian/workspace/YCTomcat/bin/
projectPath=projectPath.substring(0, projectPath.lastIndexOf("/bin/"));
System.out.println("项目的位置 :"+projectPath);
// address=/cn/in.html
File f=new File(projectPath,"/webapp/"+address);
BufferedReader reader=null;
try {
reader =new BufferedReader(new FileReader(f));
char[] buffer=new char[1024];
int length=-1;
while((length=reader.read(buffer,0,buffer.length))!=-1){
String t=new String(buffer);
htmlContent.append(t);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
htmlContent.append("<h1>404</h1>");
}catch(IOException e){
e.printStackTrace();
htmlContent.append("<h1>500</h1>");
}finally{
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return htmlContent.toString();
}
}
public class YcRequest {
private Scanner sc;
public YcRequest(Scanner sc){
this.sc=sc;
}
public String parse(){
StringBuffer address=new StringBuffer("");
//1.从scanner中读取数据,字符串
//2.从字符串中取出资源地址部分
//3.返回这个地址
if(sc.hasNext()){
address.append(sc.nextLine());
}
/* 浏览器输入http://localhost:9000/cn/in.html,然后浏览器封装了HTTP数据包
* 经过DNS解析,然后发送给主机localhost,建立一个socket双向连接
* GET /cn/in.html HTTP/1.1
*/
System.out.println("客户端传过来的http协议为:"+address);
String[] strs=address.toString().split(" ");
return strs[1];
}
}
public class YcResponse {
private PrintWriter out;
public YcResponse(PrintWriter out){
this.out=out;
}
public void writeToClient(String htmlContent){
/* 拼接好HTTP返回数据包,原来那个ajax那个200之后回送的数据包是这样拼接的 */
out.println( "HTTP/1.1 200 OK\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: "+htmlContent.getBytes().length+"\r\n\r\n" );
out.println(htmlContent);
out.flush();
out.close();
}
}
再来一个浏览器来解释数据的封装
public class Browser {
public static void main(String[] args) throws UnknownHostException, IOException {
Scanner sc=new Scanner(System.in);
String path=sc.nextLine();
URL url=new URL(path);
if("http".equals(url.getProtocol())){ //有许多协议,ftp,http,smtp等等
Socket s=new Socket(url.getHost(),url.getPort());
InputStream iis=s.getInputStream();
OutputStream oos=s.getOutputStream();
String protocal="GET "+url.getPath()+" HTTP/1.1\r\n"; //拼接的时候一定要注意
oos.write(protocal.getBytes());
oos.flush();
StringBuffer sb=new StringBuffer("");
byte[] buffer=new byte[1024];
int len=-1;
while( (len=iis.read(buffer, 0, buffer.length))!=-1 ){
String ss=new String(buffer,0,len);
sb.append(ss);
}
System.out.println(sb);
s.close();
}
}
}
下一篇讲一下有关于http协议。
我是菜鸟,我在路上。